prepare intranet for first Dokploy deployment
@@ -0,0 +1,10 @@
|
||||
.git
|
||||
.gitignore
|
||||
.env
|
||||
*.dump
|
||||
backup.sql
|
||||
*.zip
|
||||
**/__pycache__/
|
||||
**/*.pyc
|
||||
worker/ckal_upload_client/xlsx/*.xlsx
|
||||
worker/pdf_python/terminuebersicht.pdf
|
||||
@@ -0,0 +1,28 @@
|
||||
# Environment / Secrets
|
||||
.env
|
||||
|
||||
# Datenbank-Backups
|
||||
*.dump
|
||||
backup.sql
|
||||
|
||||
# Archive
|
||||
*.zip
|
||||
|
||||
# CKalender Runtime-Dateien
|
||||
worker/ckal_upload_client/xlsx/*.xlsx
|
||||
worker/pdf_python/terminuebersicht.pdf
|
||||
|
||||
# Benutzer-Profilbilder
|
||||
# default.jpg ist ein statisches Fallback-Asset und bleibt in Git
|
||||
web/intranet_repo/general_files/profile_pictures/*
|
||||
!web/intranet_repo/general_files/profile_pictures/default.jpg
|
||||
|
||||
# Contentpanel / News
|
||||
# Hochgeladene PDFs sowie daraus erzeugte PNGs sind Produktivdaten
|
||||
web/intranet_repo/projects/contentpanel/insertion/news/*
|
||||
|
||||
# Generierte Dashboard-Terminbilder
|
||||
web/intranet_repo/projects/dashboard/month/*
|
||||
|
||||
# Lokale Backup-Dateien
|
||||
*.bak
|
||||
@@ -0,0 +1,55 @@
|
||||
FROM php:8.3.33-apache-bookworm
|
||||
|
||||
ENV TZ=Europe/Berlin \
|
||||
PLAYWRIGHT_BROWSERS_PATH=/ms-playwright \
|
||||
PATH=/opt/intranet-venv/bin:$PATH
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
locales tzdata \
|
||||
python3 python3-venv \
|
||||
openssh-client ghostscript poppler-utils pngquant \
|
||||
libpq-dev libzip-dev \
|
||||
libpng-dev libjpeg62-turbo-dev libfreetype6-dev \
|
||||
&& echo 'de_DE.UTF-8 UTF-8' > /etc/locale.gen \
|
||||
&& locale-gen \
|
||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||
&& docker-php-ext-install -j"$(nproc)" pdo_pgsql pgsql zip gd \
|
||||
&& php -r '$r=["pdo_pgsql","pgsql","curl","mbstring","dom","SimpleXML","xml","xmlreader","xmlwriter","zip","gd","Zend OPcache"]; foreach($r as $e){if(!extension_loaded($e)){fwrite(STDERR,"missing PHP ext: $e\n"); exit(1);}}' \
|
||||
&& python3 -m venv /opt/intranet-venv \
|
||||
&& /opt/intranet-venv/bin/pip install --no-cache-dir --upgrade pip \
|
||||
&& /opt/intranet-venv/bin/pip install --no-cache-dir \
|
||||
beautifulsoup4==4.13.4 fpdf==1.7.2 requests==2.32.4 playwright==1.62.0 \
|
||||
&& /opt/intranet-venv/bin/python -m playwright install --with-deps chromium \
|
||||
&& chmod -R a+rX /ms-playwright \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV LANG=de_DE.UTF-8 \
|
||||
LC_ALL=de_DE.UTF-8
|
||||
|
||||
COPY docker/intranet.ini /usr/local/etc/php/conf.d/99-intranet.ini
|
||||
COPY web/ /var/www/html/
|
||||
COPY worker/ /opt/intranet/worker/
|
||||
COPY docker/scheduler.py /opt/intranet/docker/scheduler.py
|
||||
|
||||
RUN mkdir -p \
|
||||
/data/ckal-xlsx /data/pdf /data/state \
|
||||
/var/www/html/intranet_repo/general_files/profile_pictures \
|
||||
/var/www/html/intranet_repo/projects/contentpanel/insertion/news \
|
||||
/var/www/html/intranet_repo/projects/developerpanel/work \
|
||||
/var/www/html/intranet_repo/projects/seelsorge/data \
|
||||
/var/www/html/intranet_repo/projects/dashboard/month \
|
||||
&& chown -R www-data:www-data \
|
||||
/data \
|
||||
/var/www/html/intranet_repo/general_files/profile_pictures \
|
||||
/var/www/html/intranet_repo/projects/contentpanel/insertion/news \
|
||||
/var/www/html/intranet_repo/projects/developerpanel/work \
|
||||
/var/www/html/intranet_repo/projects/seelsorge/data \
|
||||
/var/www/html/intranet_repo/projects/dashboard/month \
|
||||
&& chmod +x /opt/intranet/docker/scheduler.py /opt/intranet/worker/pdf_python/pdf_to_png.sh
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
||||
CMD curl -fsS http://127.0.0.1/ >/dev/null || exit 1
|
||||
|
||||
CMD ["apache2-foreground"]
|
||||
@@ -0,0 +1,100 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "80"
|
||||
environment:
|
||||
TZ: Europe/Berlin
|
||||
INTRANET_FQDN: ${INTRANET_FQDN:?set INTRANET_FQDN}
|
||||
DB_HOST: ${DB_HOST:?set DB_HOST}
|
||||
DB_PORT: ${DB_PORT:-5432}
|
||||
DB_NAME: ${DB_NAME:?set DB_NAME}
|
||||
DB_USER: ${DB_USER:?set DB_USER}
|
||||
DB_PASSWORD: ${DB_PASSWORD:?set DB_PASSWORD}
|
||||
SMTP_HOST: ${SMTP_HOST:-smtp.strato.de}
|
||||
SMTP_PORT: ${SMTP_PORT:-587}
|
||||
SMTP_USER: ${SMTP_USER:?set SMTP_USER}
|
||||
SMTP_PASSWORD: ${SMTP_PASSWORD:?set SMTP_PASSWORD}
|
||||
ADMIN_EMAIL: ${ADMIN_EMAIL:-technik@nak-reinickendorf.de}
|
||||
SMS_GATEWAY_URL: ${SMS_GATEWAY_URL:?set SMS_GATEWAY_URL}
|
||||
HA_BASE_URL: ${HA_BASE_URL:?set HA_BASE_URL}
|
||||
HA_TOKEN: ${HA_TOKEN:?set HA_TOKEN}
|
||||
OPENWEATHER_API_KEY: ${OPENWEATHER_API_KEY:?set OPENWEATHER_API_KEY}
|
||||
CKAL_XLSX_DIR: /data/ckal-xlsx
|
||||
volumes:
|
||||
- profile_pictures:/var/www/html/intranet_repo/general_files/profile_pictures
|
||||
- content_news:/var/www/html/intranet_repo/projects/contentpanel/insertion/news
|
||||
- developer_work:/var/www/html/intranet_repo/projects/developerpanel/work
|
||||
- seelsorge_data:/var/www/html/intranet_repo/projects/seelsorge/data
|
||||
- dashboard_month:/var/www/html/intranet_repo/projects/dashboard/month
|
||||
- ckal_xlsx:/data/ckal-xlsx
|
||||
networks:
|
||||
- app
|
||||
- dokploy-network
|
||||
|
||||
scheduler:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
user: "33:33"
|
||||
command: ["/opt/intranet/docker/scheduler.py"]
|
||||
shm_size: "512m"
|
||||
environment:
|
||||
TZ: Europe/Berlin
|
||||
HOME: /tmp/intranet-worker
|
||||
XDG_CACHE_HOME: /tmp/intranet-worker-cache
|
||||
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
|
||||
INTRANET_FQDN: ${INTRANET_FQDN:?set INTRANET_FQDN}
|
||||
DB_HOST: ${DB_HOST:?set DB_HOST}
|
||||
DB_PORT: ${DB_PORT:-5432}
|
||||
DB_NAME: ${DB_NAME:?set DB_NAME}
|
||||
DB_USER: ${DB_USER:?set DB_USER}
|
||||
DB_PASSWORD: ${DB_PASSWORD:?set DB_PASSWORD}
|
||||
SMTP_HOST: ${SMTP_HOST:-smtp.strato.de}
|
||||
SMTP_PORT: ${SMTP_PORT:-587}
|
||||
SMTP_USER: ${SMTP_USER:?set SMTP_USER}
|
||||
SMTP_PASSWORD: ${SMTP_PASSWORD:?set SMTP_PASSWORD}
|
||||
ADMIN_EMAIL: ${ADMIN_EMAIL:-technik@nak-reinickendorf.de}
|
||||
CKAL_USERNAME: ${CKAL_USERNAME:?set CKAL_USERNAME}
|
||||
CKAL_PASSWORD: ${CKAL_PASSWORD:?set CKAL_PASSWORD}
|
||||
CKAL_CALENDAR_URL: ${CKAL_CALENDAR_URL:?set CKAL_CALENDAR_URL}
|
||||
CKAL_XLSX_DIR: /data/ckal-xlsx
|
||||
PDF_OUTPUT: /data/pdf/terminuebersicht.pdf
|
||||
DASHBOARD_MONTH_DIR: /var/www/html/intranet_repo/projects/dashboard/month
|
||||
CALENDAR_INTERVAL_SECONDS: ${CALENDAR_INTERVAL_SECONDS:-60}
|
||||
STRATO_SSH_HOST: ${STRATO_SSH_HOST:-ssh.strato.de}
|
||||
STRATO_SSH_PORT: ${STRATO_SSH_PORT:-22}
|
||||
STRATO_SSH_USER: ${STRATO_SSH_USER:?set STRATO_SSH_USER}
|
||||
STRATO_REMOTE_PATH: ${STRATO_REMOTE_PATH:?set STRATO_REMOTE_PATH}
|
||||
STRATO_SSH_KEY_FILE: /run/secrets/strato_ed25519
|
||||
STRATO_KNOWN_HOSTS_FILE: /run/secrets/known_hosts
|
||||
volumes:
|
||||
- dashboard_month:/var/www/html/intranet_repo/projects/dashboard/month
|
||||
- ckal_xlsx:/data/ckal-xlsx
|
||||
- calendar_pdf:/data/pdf
|
||||
- scheduler_state:/data/state
|
||||
- ../files/strato_ed25519:/run/secrets/strato_ed25519:ro
|
||||
- ../files/known_hosts:/run/secrets/known_hosts:ro
|
||||
networks:
|
||||
- app
|
||||
- dokploy-network
|
||||
|
||||
volumes:
|
||||
profile_pictures:
|
||||
content_news:
|
||||
developer_work:
|
||||
seelsorge_data:
|
||||
dashboard_month:
|
||||
ckal_xlsx:
|
||||
calendar_pdf:
|
||||
scheduler_state:
|
||||
|
||||
networks:
|
||||
app:
|
||||
dokploy-network:
|
||||
external: true
|
||||
@@ -0,0 +1,11 @@
|
||||
date.timezone = Europe/Berlin
|
||||
upload_max_filesize = 64M
|
||||
post_max_size = 70M
|
||||
memory_limit = 512M
|
||||
max_execution_time = 180
|
||||
display_errors = Off
|
||||
log_errors = On
|
||||
session.cookie_httponly = 1
|
||||
session.cookie_samesite = Lax
|
||||
session.cookie_secure = 1
|
||||
expose_php = Off
|
||||
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env python3
|
||||
import fcntl
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
PYTHON = '/opt/intranet-venv/bin/python'
|
||||
ROOT = Path('/opt/intranet/worker')
|
||||
STATE_DIR = Path('/data/state')
|
||||
PDF_OUTPUT = Path(os.getenv('PDF_OUTPUT', '/data/pdf/terminuebersicht.pdf'))
|
||||
INTERVAL = int(os.getenv('CALENDAR_INTERVAL_SECONDS', '60'))
|
||||
|
||||
|
||||
def required(name: str) -> str:
|
||||
value = os.getenv(name, '').strip()
|
||||
if not value:
|
||||
raise RuntimeError(f'Missing environment variable: {name}')
|
||||
return value
|
||||
|
||||
|
||||
def run(cmd, cwd=None):
|
||||
print('+', ' '.join(map(str, cmd)), flush=True)
|
||||
subprocess.run(cmd, cwd=cwd, check=True, env=os.environ.copy())
|
||||
|
||||
|
||||
def prepare_ssh_key() -> Path:
|
||||
source = Path(os.getenv('STRATO_SSH_KEY_FILE', '/run/secrets/strato_ed25519'))
|
||||
if not source.is_file():
|
||||
raise RuntimeError(f'SSH key file missing: {source}')
|
||||
target = Path('/tmp/strato_ed25519')
|
||||
shutil.copyfile(source, target)
|
||||
target.chmod(0o600)
|
||||
return target
|
||||
|
||||
|
||||
def calendar_sync():
|
||||
run([PYTHON, str(ROOT / 'ckal_upload_client/client.py')], cwd=ROOT / 'ckal_upload_client')
|
||||
run([PYTHON, str(ROOT / 'pdf_python/create_pdf.py')], cwd=ROOT / 'pdf_python')
|
||||
run(['/bin/bash', str(ROOT / 'pdf_python/pdf_to_png.sh')], cwd=ROOT / 'pdf_python')
|
||||
|
||||
required('STRATO_SSH_USER')
|
||||
required('STRATO_REMOTE_PATH')
|
||||
host = os.getenv('STRATO_SSH_HOST', 'ssh.strato.de')
|
||||
port = os.getenv('STRATO_SSH_PORT', '22')
|
||||
known_hosts = Path(os.getenv('STRATO_KNOWN_HOSTS_FILE', '/run/secrets/known_hosts'))
|
||||
if not known_hosts.is_file():
|
||||
raise RuntimeError(f'known_hosts missing: {known_hosts}')
|
||||
key = prepare_ssh_key()
|
||||
if not PDF_OUTPUT.is_file() or PDF_OUTPUT.stat().st_size == 0:
|
||||
raise RuntimeError(f'PDF missing/empty: {PDF_OUTPUT}')
|
||||
|
||||
run([
|
||||
'/usr/bin/scp', '-O', '-q', '-P', port,
|
||||
'-i', str(key),
|
||||
'-o', 'IdentitiesOnly=yes',
|
||||
'-o', 'BatchMode=yes',
|
||||
'-o', 'StrictHostKeyChecking=yes',
|
||||
'-o', f'UserKnownHostsFile={known_hosts}',
|
||||
str(PDF_OUTPUT),
|
||||
f"{required('STRATO_SSH_USER')}@{host}:{required('STRATO_REMOTE_PATH')}",
|
||||
])
|
||||
print('Calendar Sync erfolgreich', flush=True)
|
||||
|
||||
|
||||
def brandschutz_once_per_month():
|
||||
now = datetime.now()
|
||||
if now.day != 1 or now.hour < 8:
|
||||
return
|
||||
|
||||
marker = STATE_DIR / 'brandschutz-last-attempt'
|
||||
month = now.strftime('%Y-%m')
|
||||
if marker.exists() and marker.read_text().strip() == month:
|
||||
return
|
||||
|
||||
# At-most-once: erst markieren, dann ausführen. Bei Fehler manuell prüfen und Marker löschen.
|
||||
marker.write_text(month + '\n')
|
||||
print(f'Brandschutz-Lauf {month}', flush=True)
|
||||
run(['/usr/local/bin/php', '/var/www/html/intranet_repo/projects/brandschutz/brandschutz_cron.php'])
|
||||
|
||||
|
||||
def main():
|
||||
STATE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
lock_handle = (STATE_DIR / 'scheduler.lock').open('w')
|
||||
try:
|
||||
fcntl.flock(lock_handle.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except BlockingIOError as exc:
|
||||
raise RuntimeError('Ein anderer Scheduler läuft bereits.') from exc
|
||||
|
||||
if INTERVAL < 30:
|
||||
raise RuntimeError('CALENDAR_INTERVAL_SECONDS muss >= 30 sein.')
|
||||
for name in ('CKAL_USERNAME', 'CKAL_PASSWORD', 'CKAL_CALENDAR_URL'):
|
||||
required(name)
|
||||
PDF_OUTPUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
next_run = 0.0
|
||||
while True:
|
||||
try:
|
||||
brandschutz_once_per_month()
|
||||
except Exception as exc:
|
||||
print(f'FEHLER Brandschutz: {exc}', flush=True)
|
||||
|
||||
now_mono = time.monotonic()
|
||||
if now_mono >= next_run:
|
||||
try:
|
||||
calendar_sync()
|
||||
except Exception as exc:
|
||||
print(f'FEHLER Calendar Sync: {exc}', flush=True)
|
||||
next_run = time.monotonic() + INTERVAL
|
||||
|
||||
(STATE_DIR / 'heartbeat').write_text(str(int(time.time())) + '\n')
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php session_start();
|
||||
header("Location: /intranet_repo/projects/dashboard/dashboard.php");
|
||||
exit;
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php session_start();
|
||||
header("Location: /intranet_repo/projects/intranet/index.php");
|
||||
exit;
|
||||
@@ -0,0 +1,2 @@
|
||||
# pool_nak
|
||||
Entwicklungsumgebung für das Seelsorge-Interface.
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*
|
||||
Name: content/kalender.php
|
||||
Beschreibung: Übersicht: Kalenderblatt
|
||||
|
||||
Cookie-Setting: calendarDate = {$datum} -> Format: "Y-m-d"
|
||||
*/
|
||||
|
||||
require_once('util/connector_feiertage.php');
|
||||
$connector_feiertage = lib_Feiertage_Connector::getInstance();
|
||||
require_once('util/connector_kalendertage.php');
|
||||
$connector_kalendertage = lib_Kalendertage_Connector::getInstance();
|
||||
|
||||
$pdo = require($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
?>
|
||||
|
||||
<?php
|
||||
if (isset($_GET['action']) && $_GET['action'] === 'edit') {
|
||||
include $_SERVER['DOCUMENT_ROOT']."/intranet_repo/projects/seelsorge/content/kalender_edit.php";
|
||||
} else {
|
||||
include $_SERVER['DOCUMENT_ROOT']."/intranet_repo/projects/seelsorge/content/kalender_view.php";
|
||||
}
|
||||
?>
|
||||
|
||||
<script>
|
||||
function toggleView() {
|
||||
var currentUrl = window.location.href;
|
||||
var baseUrl = currentUrl.split('?')[0];
|
||||
var newUrl;
|
||||
|
||||
if (currentUrl.includes('action=edit')) {
|
||||
newUrl = baseUrl;
|
||||
} else {
|
||||
newUrl = baseUrl + '?action=edit';
|
||||
}
|
||||
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<?php
|
||||
if (isset($_GET['action']) && $_GET['action'] === 'edit') { ?>
|
||||
<button onclick="toggleView()">View</button>
|
||||
<?php } else { ?>
|
||||
<button onclick="toggleView()"><svg fill="none" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><g stroke="#a649da" stroke-linecap="round" stroke-width="2"><path d="m20 20h-16"></path><path clip-rule="evenodd" d="m14.5858 4.41422c.781-.78105 2.0474-.78105 2.8284 0 .7811.78105.7811 2.04738 0 2.82843l-8.28322 8.28325-3.03046.202.20203-3.0304z" fill-rule="evenodd"></path></g></svg>
|
||||
<span class="lable">Edit</span></button>
|
||||
<?php } ?>
|
||||
|
||||
<script>
|
||||
function toggleAvailability(date, clickedElement) {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
console.log(this.responseText);
|
||||
clickedElement.classList.toggle("normalday");
|
||||
clickedElement.classList.toggle("availableday");
|
||||
}
|
||||
};
|
||||
xhttp.open("POST", "toggle_availability.php", true);
|
||||
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhttp.send("date=" + date);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,756 @@
|
||||
/*
|
||||
Name: kalli.css
|
||||
Beschreibung: Spezielles CSS für KALLI
|
||||
|
||||
TODO: LÖSCHEN - WIRD NICHT MEHR EINGESETZT
|
||||
*/
|
||||
a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header_menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
height: 7%;
|
||||
width: 100vw;
|
||||
background-color: #5793c9;
|
||||
border-bottom: 4px solid #c3e2ff;
|
||||
z-index: 1000; /* Z-Index erhöhen, um sicherzustellen, dass der Header über anderen Elementen liegt */
|
||||
position: fixed;
|
||||
}
|
||||
.header_menu a {
|
||||
height: 100%;
|
||||
}
|
||||
.header_menu img {
|
||||
height: 100%;
|
||||
}
|
||||
.content {
|
||||
position: absolute;
|
||||
width: 100vw;;
|
||||
top: 8%;
|
||||
}
|
||||
.profile {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.center {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.center a {
|
||||
padding: 0 10px 0 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.center img {
|
||||
height: 80%;
|
||||
max-height: 50px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
object-fit: cover;
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.alert{
|
||||
background-color: #f44336 !important;
|
||||
}
|
||||
|
||||
.spacer{
|
||||
height: 6em;
|
||||
}
|
||||
|
||||
.content-spacer {
|
||||
min-height: calc( 100vh - 67px);
|
||||
}
|
||||
|
||||
.legal {
|
||||
margin: auto;
|
||||
max-width: 63em;
|
||||
min-width: 0em;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.legal a {
|
||||
color: #5793c9;
|
||||
}
|
||||
|
||||
.legal a:hover {
|
||||
color: #1c5282;
|
||||
}
|
||||
|
||||
.pdf {
|
||||
margin: auto;
|
||||
width: 70vw;
|
||||
height: 50em;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
#pdf {
|
||||
display: none;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
margin: 3em;
|
||||
}
|
||||
|
||||
#pdf:hover{
|
||||
color: #1c5282;
|
||||
}
|
||||
|
||||
@media screen and (max-width:650px) {
|
||||
.pdf{
|
||||
display: none;
|
||||
}
|
||||
#pdf{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.event-box {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 10px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box0 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 10px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
min-width: 20em;
|
||||
justify-content: center; /* Center horizontally */
|
||||
align-items: center; /* Center vertically */
|
||||
}
|
||||
|
||||
|
||||
.event-box1 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box2 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box3 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #ffffff;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box4 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 10px 1em;
|
||||
display: flex;
|
||||
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box5 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #1c5282;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box6 {
|
||||
overflow-x: scroll; /*ACHTUNG!*/
|
||||
max-width: 80vw;
|
||||
background-color: #c3e2ff;
|
||||
margin: auto;
|
||||
padding: 5px 1em;
|
||||
}
|
||||
|
||||
.group-column {
|
||||
flex-grow: 10; /* default 0 */
|
||||
padding: 10px 1em;
|
||||
}
|
||||
|
||||
.event {
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.event1 {
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.event-box a {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
.svg1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 0 15px 0 20px;
|
||||
}
|
||||
|
||||
.news {
|
||||
width: fit-content;
|
||||
padding: 1em;
|
||||
background-color: #5793c9;
|
||||
border-radius: 5px;
|
||||
margin: 3em auto;
|
||||
}
|
||||
|
||||
.news1 {
|
||||
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.news2 {
|
||||
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.news3 {
|
||||
width: fit-content;
|
||||
padding: 0.5em;
|
||||
background-color: #5793c9;
|
||||
border-radius: 5px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.news2:hover {
|
||||
|
||||
background-color: #1c5282;
|
||||
|
||||
}
|
||||
|
||||
.news3:hover {
|
||||
|
||||
background-color: #1c5282;
|
||||
|
||||
}
|
||||
|
||||
.null {
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.news a{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
align-content: flex-end;
|
||||
}
|
||||
|
||||
.svg-news {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.form-div {
|
||||
margin: auto;
|
||||
max-width: 70vw;
|
||||
width: 30em;
|
||||
padding: 1em;
|
||||
background-color: #c3e2ff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.form-div1 {
|
||||
margin: auto;
|
||||
max-width: 70vw;
|
||||
width: 30em;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
input[type=text], select {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
textarea, select {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type=number], select {
|
||||
width: 100%;
|
||||
padding: 5px 1px 5px 5px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type=submit] {
|
||||
width: 100%;
|
||||
background-color: #5793c9;
|
||||
color: white;
|
||||
padding: 14px 20px;
|
||||
margin: 8px 0;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=submit]:hover {
|
||||
background-color: #2a6193;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
height: 3em;
|
||||
border-top: #5793c9 3px solid;
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
footer a:hover{
|
||||
color: #5793c9;
|
||||
}
|
||||
|
||||
.legal-links {
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.legal-links a {
|
||||
margin: 0 1em;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
#mySidenav a {
|
||||
position: absolute; /* Position them relative to the browser window */
|
||||
position: fixed;
|
||||
right: -80px; /* Position them outside of the screen */
|
||||
transition: 0.3s; /* Add transition on hover */
|
||||
padding: 15px; /* 15px padding */
|
||||
width: 100px; /* Set a specific width */
|
||||
text-decoration: none; /* Remove underline */
|
||||
font-size: 20px; /* Increase font size */
|
||||
color: white; /* White text color */
|
||||
border-radius: 5px 0 0 5px; /* Rounded corners on the top right and bottom right side */
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
#mySidenav a:hover {
|
||||
right: 0; /* On mouse-over, make the elements appear as they should */
|
||||
}
|
||||
|
||||
/* The about link: 20px from the top with a green background */
|
||||
#admin {
|
||||
top: 15px;
|
||||
background-color: #5793c9;
|
||||
}
|
||||
|
||||
|
||||
/* Style the Image Used to Trigger the Modal */
|
||||
#myImg {
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* On mouse-over, add a deeper shadow */
|
||||
#myImg:hover {
|
||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.box2 {
|
||||
width: 100%;
|
||||
padding: 5px 0;
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.box2:hover {
|
||||
max-width: 800px;
|
||||
font-size: 20pt;
|
||||
transition: 1s;
|
||||
}
|
||||
|
||||
.box3 {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Add some padding inside the card container */
|
||||
.container {
|
||||
padding: 2px 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container_flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
max-width: 550px;
|
||||
min-width: 120px;
|
||||
background-color: #35374b;
|
||||
margin: 0.5em auto;
|
||||
padding: 0px;
|
||||
color: #fff;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
width: 90%;
|
||||
margin: 0.75em auto;
|
||||
padding: 7px;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_row_2 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-evenly;
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container_flex_row_bg {
|
||||
background-color: #c3e2ff;
|
||||
border-radius: 7px;
|
||||
margin: 1em auto 1em auto;
|
||||
width: 90%;
|
||||
padding: 3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
.time_group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.container_today {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
max-width: 550px;
|
||||
min-width: 90px;
|
||||
background-color: #35374b;
|
||||
margin: 0.75em auto;
|
||||
padding: 7px;
|
||||
color: #fff;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
max-width: 550px;
|
||||
background-color: #3478a2;
|
||||
margin: 0.75em auto;
|
||||
color: #fff;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_casual {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
max-width: 650px;
|
||||
background-color: #35374b;
|
||||
padding: 0 1em 0 1em;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
margin: 0 0.75em 0 0.75em;
|
||||
}
|
||||
|
||||
.container_flex_casual_2 {
|
||||
background-color: #35374b;
|
||||
padding: 1em 1em 1em 1em;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
max-height: 100px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.container_flex_casual_2 img {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container_flex_time {
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
background-color: #35374b;
|
||||
margin: 5px;
|
||||
font-size: 25;
|
||||
padding: 12px 20px 12px 20px;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.container_flex_time p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container_flex_topbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px 0 10px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.vertical_spacer {
|
||||
height: 100%;
|
||||
margin: auto 0 auto 0;
|
||||
}
|
||||
|
||||
.container_flex_2 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0px 10px 0px;
|
||||
border-radius: 7px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container_flex_weather {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px 10px 10px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.container_flex_3 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-evenly;
|
||||
background-color: #3b3c4e;
|
||||
width: 593px;
|
||||
padding: 10px 10px 10px 10px;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
|
||||
}
|
||||
|
||||
.container_flex_bg {
|
||||
background-color: #c3e2ff;
|
||||
border-radius: 7px;
|
||||
padding: 3px 10px 3px 10px;
|
||||
}
|
||||
|
||||
.item_flex_2 {
|
||||
margin: 0.2em;
|
||||
}
|
||||
|
||||
.item_flex_oben {
|
||||
margin: 0.75em auto auto auto;
|
||||
}
|
||||
|
||||
.item_flex_rechts {
|
||||
margin: auto 0.2em auto auto;
|
||||
}
|
||||
|
||||
.item_flex_links {
|
||||
margin: auto auto auto 0.2em;
|
||||
}
|
||||
|
||||
.opnv-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0 0 0 20px;
|
||||
}
|
||||
|
||||
.temp-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.temp-icon-house {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 7px 0 7px 5px;
|
||||
}
|
||||
|
||||
.temp-icon-today img {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
padding: 5px 5px 5px 5px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.temp-icon-house img {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
margin: auto 2em auto auto;
|
||||
}
|
||||
|
||||
.temp-line {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0 10 0 0px;
|
||||
}
|
||||
|
||||
|
||||
.item_flex.line {
|
||||
max-width: 300px;
|
||||
padding: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
.h2_test {
|
||||
font-size:25px;
|
||||
padding: 15px 0 0 0;
|
||||
}
|
||||
|
||||
.item_flex.line p{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item_flex.time-remain{
|
||||
text-align: center;
|
||||
margin: 0 20px 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.item_flex.time-remain *{
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0.2em;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: .2em .5em;
|
||||
border-radius: .1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
td {
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
box-shadow: inset 1px 3px 5px -3px rgb(0 0 0 / .5);
|
||||
}
|
||||
|
||||
td:empty{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) {
|
||||
background-color: #e4ebf2;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.rechtsbuendig {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.bosskoddes {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,789 @@
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
*{
|
||||
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
}
|
||||
a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
color: white;
|
||||
}
|
||||
|
||||
.header_menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
height: 7%;
|
||||
width: 100vw;
|
||||
background-color: #5793c9;
|
||||
border-bottom: 4px solid #c3e2ff;
|
||||
z-index: 1000; /* Z-Index erhöhen, um sicherzustellen, dass der Header über anderen Elementen liegt */
|
||||
position: fixed;
|
||||
}
|
||||
.header_menu a {
|
||||
height: 100%;
|
||||
}
|
||||
.header_menu img {
|
||||
height: 100%;
|
||||
}
|
||||
.content {
|
||||
position: absolute;
|
||||
width: 100vw;;
|
||||
top: 8%;
|
||||
}
|
||||
.profile {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.center {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.center a {
|
||||
padding: 0 10px 0 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.center img {
|
||||
height: 80%;
|
||||
max-height: 50px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
object-fit: cover;
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-box {
|
||||
|
||||
background-color: #04AA6D;
|
||||
color: #fefefe;
|
||||
margin: auto;
|
||||
height: 3em;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
min-width: fit-content;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.error-box1 {
|
||||
|
||||
background-color: #f44336;
|
||||
color: #fefefe;
|
||||
margin: auto;
|
||||
height: 3em;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
min-width: fit-content;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.alert{
|
||||
background-color: #f44336 !important;
|
||||
}
|
||||
|
||||
.spacer{
|
||||
height: 6em;
|
||||
}
|
||||
|
||||
.content-spacer {
|
||||
min-height: calc( 100vh - 67px);
|
||||
}
|
||||
|
||||
.legal {
|
||||
margin: auto;
|
||||
max-width: 63em;
|
||||
min-width: 0em;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.legal a {
|
||||
color: #5793c9;
|
||||
}
|
||||
|
||||
.legal a:hover {
|
||||
color: #1c5282;
|
||||
}
|
||||
|
||||
.pdf {
|
||||
margin: auto;
|
||||
width: 70vw;
|
||||
height: 50em;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
#pdf {
|
||||
display: none;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
margin: 3em;
|
||||
}
|
||||
|
||||
#pdf:hover{
|
||||
color: #1c5282;
|
||||
}
|
||||
|
||||
@media screen and (max-width:650px) {
|
||||
.pdf{
|
||||
display: none;
|
||||
}
|
||||
#pdf{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.event-box {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 10px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box0 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 10px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
min-width: 20em;
|
||||
justify-content: center; /* Center horizontally */
|
||||
align-items: center; /* Center vertically */
|
||||
}
|
||||
|
||||
|
||||
.event-box1 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box2 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box3 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #ffffff;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box4 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #c3e2ff;
|
||||
padding: 10px 1em;
|
||||
display: flex;
|
||||
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box5 {
|
||||
max-width: 60vw;
|
||||
margin: auto;
|
||||
background-color: #1c5282;
|
||||
padding: 0px 1em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
min-width: 20em;
|
||||
}
|
||||
|
||||
.event-box6 {
|
||||
overflow-x: scroll; /*ACHTUNG!*/
|
||||
max-width: 80vw;
|
||||
background-color: #c3e2ff;
|
||||
margin: auto;
|
||||
padding: 5px 1em;
|
||||
}
|
||||
|
||||
.group-column {
|
||||
flex-grow: 10; /* default 0 */
|
||||
padding: 10px 1em;
|
||||
}
|
||||
|
||||
.event {
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.event1 {
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.event-box a {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
.svg1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 0 15px 0 20px;
|
||||
}
|
||||
|
||||
.news {
|
||||
width: fit-content;
|
||||
padding: 1em;
|
||||
background-color: #5793c9;
|
||||
border-radius: 5px;
|
||||
margin: 3em auto;
|
||||
}
|
||||
|
||||
.news1 {
|
||||
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.news2 {
|
||||
|
||||
background-color: #5793c9;
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.news3 {
|
||||
width: fit-content;
|
||||
padding: 0.5em;
|
||||
background-color: #5793c9;
|
||||
border-radius: 5px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.news2:hover {
|
||||
|
||||
background-color: #1c5282;
|
||||
|
||||
}
|
||||
|
||||
.news3:hover {
|
||||
|
||||
background-color: #1c5282;
|
||||
|
||||
}
|
||||
|
||||
.null {
|
||||
margin: 15px 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.news a{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
align-content: flex-end;
|
||||
}
|
||||
|
||||
.svg-news {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.form-div {
|
||||
margin: auto;
|
||||
max-width: 70vw;
|
||||
width: 30em;
|
||||
padding: 1em;
|
||||
background-color: #c3e2ff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.form-div1 {
|
||||
margin: auto;
|
||||
max-width: 70vw;
|
||||
width: 30em;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
input[type=text], select {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
textarea, select {
|
||||
width: 100%;
|
||||
padding: 12px 20px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type=number], select {
|
||||
width: 100%;
|
||||
padding: 5px 1px 5px 5px;
|
||||
margin: 8px 0;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type=submit] {
|
||||
width: 100%;
|
||||
background-color: #5793c9;
|
||||
color: white;
|
||||
padding: 14px 20px;
|
||||
margin: 8px 0;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=submit]:hover {
|
||||
background-color: #2a6193;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
height: 3em;
|
||||
border-top: #5793c9 3px solid;
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
footer a:hover{
|
||||
color: #5793c9;
|
||||
}
|
||||
|
||||
.legal-links {
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.legal-links a {
|
||||
margin: 0 1em;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
#mySidenav a {
|
||||
position: absolute; /* Position them relative to the browser window */
|
||||
position: fixed;
|
||||
right: -80px; /* Position them outside of the screen */
|
||||
transition: 0.3s; /* Add transition on hover */
|
||||
padding: 15px; /* 15px padding */
|
||||
width: 100px; /* Set a specific width */
|
||||
text-decoration: none; /* Remove underline */
|
||||
font-size: 20px; /* Increase font size */
|
||||
color: white; /* White text color */
|
||||
border-radius: 5px 0 0 5px; /* Rounded corners on the top right and bottom right side */
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
#mySidenav a:hover {
|
||||
right: 0; /* On mouse-over, make the elements appear as they should */
|
||||
}
|
||||
|
||||
/* The about link: 20px from the top with a green background */
|
||||
#admin {
|
||||
top: 15px;
|
||||
background-color: #5793c9;
|
||||
}
|
||||
|
||||
|
||||
/* Style the Image Used to Trigger the Modal */
|
||||
#myImg {
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* On mouse-over, add a deeper shadow */
|
||||
#myImg:hover {
|
||||
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.box2 {
|
||||
width: 100%;
|
||||
padding: 5px 0;
|
||||
max-width: 600px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.box2:hover {
|
||||
max-width: 800px;
|
||||
font-size: 20pt;
|
||||
transition: 1s;
|
||||
}
|
||||
|
||||
.box3 {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Add some padding inside the card container */
|
||||
.container {
|
||||
padding: 2px 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container_flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
max-width: 550px;
|
||||
min-width: 120px;
|
||||
background-color: #35374b;
|
||||
margin: 0.5em auto;
|
||||
padding: 0px;
|
||||
color: #fff;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
width: 90%;
|
||||
margin: 0.75em auto;
|
||||
padding: 7px;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_row_2 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-evenly;
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container_flex_row_bg {
|
||||
background-color: #c3e2ff;
|
||||
border-radius: 7px;
|
||||
margin: 1em auto 1em auto;
|
||||
width: 90%;
|
||||
padding: 3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
.time_group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.container_today {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
max-width: 550px;
|
||||
min-width: 90px;
|
||||
background-color: #35374b;
|
||||
margin: 0.75em auto;
|
||||
padding: 7px;
|
||||
color: #fff;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
max-width: 550px;
|
||||
background-color: #3478a2;
|
||||
margin: 0.75em auto;
|
||||
color: #fff;
|
||||
border-radius: 7px
|
||||
}
|
||||
|
||||
.container_flex_casual {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
max-width: 650px;
|
||||
background-color: #35374b;
|
||||
padding: 0 1em 0 1em;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
margin: 0 0.75em 0 0.75em;
|
||||
}
|
||||
|
||||
.container_flex_casual_2 {
|
||||
background-color: #35374b;
|
||||
padding: 1em 1em 1em 1em;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
max-height: 100px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.container_flex_casual_2 img {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container_flex_time {
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
background-color: #35374b;
|
||||
margin: 5px;
|
||||
font-size: 25;
|
||||
padding: 12px 20px 12px 20px;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.container_flex_time p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container_flex_topbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px 0 10px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.vertical_spacer {
|
||||
height: 100%;
|
||||
margin: auto 0 auto 0;
|
||||
}
|
||||
|
||||
.container_flex_2 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0px 10px 0px;
|
||||
border-radius: 7px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.container_flex_weather {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px 10px 10px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.container_flex_3 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-evenly;
|
||||
background-color: #3b3c4e;
|
||||
width: 593px;
|
||||
padding: 10px 10px 10px 10px;
|
||||
color: #fff;
|
||||
border-radius: 7px;
|
||||
|
||||
}
|
||||
|
||||
.container_flex_bg {
|
||||
background-color: #c3e2ff;
|
||||
border-radius: 7px;
|
||||
padding: 3px 10px 3px 10px;
|
||||
}
|
||||
|
||||
.item_flex_2 {
|
||||
margin: 0.2em;
|
||||
}
|
||||
|
||||
.item_flex_oben {
|
||||
margin: 0.75em auto auto auto;
|
||||
}
|
||||
|
||||
.item_flex_rechts {
|
||||
margin: auto 0.2em auto auto;
|
||||
}
|
||||
|
||||
.item_flex_links {
|
||||
margin: auto auto auto 0.2em;
|
||||
}
|
||||
|
||||
.opnv-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0 0 0 20px;
|
||||
}
|
||||
|
||||
.temp-icon {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.temp-icon-house {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 7px 0 7px 5px;
|
||||
}
|
||||
|
||||
.temp-icon-today img {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
padding: 5px 5px 5px 5px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.temp-icon-house img {
|
||||
display: block;
|
||||
justify-content: center;
|
||||
margin: auto 2em auto auto;
|
||||
}
|
||||
|
||||
.temp-line {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 0 10 0 0px;
|
||||
}
|
||||
|
||||
|
||||
.item_flex.line {
|
||||
max-width: 300px;
|
||||
padding: 0px 10px 0px 10px;
|
||||
}
|
||||
|
||||
.h2_test {
|
||||
font-size:25px;
|
||||
padding: 15px 0 0 0;
|
||||
}
|
||||
|
||||
.item_flex.line p{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.item_flex.time-remain{
|
||||
text-align: center;
|
||||
margin: 0 20px 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.item_flex.time-remain *{
|
||||
margin: 0;
|
||||
}
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0.2em;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: .2em .5em;
|
||||
border-radius: .1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
td {
|
||||
font-style: italic;
|
||||
text-align: right;
|
||||
box-shadow: inset 1px 3px 5px -3px rgb(0 0 0 / .5);
|
||||
}
|
||||
|
||||
td:empty{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even) {
|
||||
background-color: #e4ebf2;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.rechtsbuendig {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.bosskoddes {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: none;
|
||||
}
|
||||
|
After Width: | Height: | Size: 28 KiB |
@@ -0,0 +1,774 @@
|
||||
/* Name: seelsorge.css
|
||||
Beschreibung: Spezielles CSS für Seelsorge Planer */
|
||||
|
||||
#seelsorge.menue {
|
||||
position:relative;
|
||||
top: 0px;
|
||||
display: flex;
|
||||
margin: 0px 0px 0px 0px;
|
||||
height: fit-content;
|
||||
width: 100%;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
transition: top 0.9s ease-in-out;
|
||||
}
|
||||
#seelsorge.menue .list {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
margin: 0 1.8vw 0 1.8vw;
|
||||
padding: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#seelsorge.menue .menu-item:link {color: hsl(210, 60%, 50%);}
|
||||
#seelsorge.menue .menu-item:hover {color: #FEFEFE; opacity: 1.0; transition: top 0.6s ease-in-out;}
|
||||
#seelsorge.menue .active {
|
||||
/*background-color: hsl(210, 80%, 35%) !important;*/
|
||||
color: #FEFEFE !important;
|
||||
font-weight: 400 !important;
|
||||
/*box-shadow: 0 0 2px 1px rgba(255, 255, 255, 0.4),
|
||||
0 1px 12px 0 rgba(0, 0, 0, 0.5) !important;*/
|
||||
opacity: 1.0 !important;
|
||||
}
|
||||
|
||||
#seelsorge.menue .menu-item {
|
||||
padding: 0px;
|
||||
margin: 0px 0px 0px 30px;
|
||||
display: block;
|
||||
width: 175px;
|
||||
max-width: 24vw;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
/*border-radius: 9999px;*/
|
||||
color: #DDDDDD;
|
||||
font-size: 100%;
|
||||
font-weight: 100;
|
||||
cursor: pointer;
|
||||
opacity: 0.9;
|
||||
|
||||
transition: background-color 0.5s ease;
|
||||
/*box-shadow: 0 1px 1px 0 rgba(255, 255, 255, 0.3),
|
||||
0 1px 6px 0 rgba(0, 0, 0, 0.2);*/
|
||||
}
|
||||
#seelsorge.menue .indicator {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: -3px;
|
||||
width: 0px;
|
||||
border-bottom: 2px solid #FEFEFE;
|
||||
transition: width 0.9s ease-in-out, left 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
.content_seelsorge {
|
||||
position: relative;
|
||||
display: none; /* Ausblenden, wird per Javascript gesteuert */
|
||||
justify-content: center;
|
||||
justify-self: center;
|
||||
padding: 5px;
|
||||
margin-top: 0px;
|
||||
width: calc(100% - 20px - 2px); /* Abzug von Padding+Border */
|
||||
min-height: 100%;
|
||||
border: 1px solid #DDDDDD;
|
||||
border-radius: 5px;
|
||||
background-color: hsl( 60, 33%, 100%);
|
||||
}
|
||||
.content .active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
p {font-size: 10pt;}
|
||||
.long {text-align: justify;}
|
||||
.up {text-transform: uppercase;}
|
||||
.low {text-transform: lowercase;}
|
||||
.capital {text-transform: capitalize;}
|
||||
|
||||
table, div.table {
|
||||
display: table;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
align-items: center;
|
||||
border: 0px solid #000000;
|
||||
}
|
||||
|
||||
/* Spezielle Styles */
|
||||
div.title {
|
||||
display: table;
|
||||
-ms-flex: 100%;
|
||||
flex: 100%;
|
||||
margin: 5px;
|
||||
background-color: transparent;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.3);
|
||||
background: linear-gradient(to top left,
|
||||
hsl(60, 33%, 70%) 0%,
|
||||
hsl(195, 33%, 70%) 100%);
|
||||
}
|
||||
p.title {
|
||||
margin: 0px;
|
||||
background-color: hsl(297, 50%, 20%);
|
||||
-webkit-background-clip: text;
|
||||
-moz-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
text-shadow: rgba(255,255,255,0.5) 0px 3px 3px;
|
||||
font-size: 31pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Wiederholbare Styles*/
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
.right {
|
||||
text-align : right;
|
||||
}
|
||||
|
||||
img.header {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
height: 100px;
|
||||
width: auto;
|
||||
max-height: 100px;
|
||||
border: 0px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* div.menue {
|
||||
-ms-flex: 80px;
|
||||
flex: 80px;
|
||||
flex-flow: column wrap;
|
||||
padding: 15px 5px 5px 5px;
|
||||
margin: 5px;
|
||||
height: auto;
|
||||
align-items: center;
|
||||
|
||||
border: 6px solid hsl(60, 33%, 90%) ;
|
||||
border-radius: 6px;
|
||||
background-color: hsl(60, 33%, 75%);
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2),
|
||||
0 6px 20px 0 rgba(0, 0, 0, 0.3);
|
||||
|
||||
text-align: left;
|
||||
font-family: Bahnschrift, Arial;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
} */
|
||||
/* div.menue a:link {color: hsl(195, 60%, 50%);}
|
||||
div.menue a:visited {color: hsl(195, 60%, 50%);}
|
||||
div.menue a:hover {color: hsl(195, 100%, 100%);}
|
||||
div.menue a:active {color: hsl(195, 20%, 50%);}
|
||||
div.menue a.currentPage {background-color: hsl(208, 50%, 70%); color: hsl(195, 50%, 20%);}
|
||||
div.menue ul {
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
|
||||
list-style-type: none;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
} */
|
||||
/* div.menue ul a {
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
margin: 5px;
|
||||
margin-left: 0px;
|
||||
display: block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
border-radius: 20px;
|
||||
text-decoration: none;
|
||||
background-color: hsl(60, 33%, 100%);
|
||||
border: 0px solid hsl(195, 0%, 80%);
|
||||
transition: background-color 0.5s ease;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 6px 0 rgba(0, 0, 0, 0.2);
|
||||
} */
|
||||
/* div.menue ul a:hover {
|
||||
border: 0px solid hsl(60, 33%, 100%);
|
||||
opacity: 1;
|
||||
color: hsl(60, 50%, 80%);
|
||||
background-color: hsl(208, 60%, 35%);
|
||||
box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.4), 0 1px 12px 0 rgba(0, 0, 0, 0.4);
|
||||
|
||||
}
|
||||
img.menue_bg {
|
||||
width: 90px;
|
||||
padding-top: 15px;
|
||||
opacity: 0.7;
|
||||
} */
|
||||
|
||||
/* Content-Styles: Output und Panels */
|
||||
/* div.content {
|
||||
display: flex;
|
||||
-ms-flex: 70%;
|
||||
flex: 70%;
|
||||
flex-flow: row wrap;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
max-height: calc(100vh - 37px - 140px);
|
||||
overflow: auto;
|
||||
background-color: hsl(60, 33%, 90%);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.3);
|
||||
} */
|
||||
|
||||
div.content_panel form {
|
||||
padding: 0px;
|
||||
padding-top: 0px;
|
||||
margin: 0px;
|
||||
margin-top: 10px;
|
||||
/*overflow: auto;*/
|
||||
width: calc(100% - 0px); /* Abzug von Abständen */
|
||||
height: calc(100vh - 37px - 140px - 100px + 2px); /* Abzug von Abständen */
|
||||
/*background-color: hsl( 60, 33%, 95%);*/
|
||||
}
|
||||
div.content_panel input {
|
||||
/* margin-top: 5px; */
|
||||
margin-left: 0px;
|
||||
padding: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
width: 120px;
|
||||
color: hsl(60, 33%, 75%);
|
||||
background-color: hsl(208, 50%, 30%);
|
||||
border: 2px solid #AAA;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.content_output {
|
||||
padding: 15px;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin: 0px;
|
||||
margin-top: 10px;
|
||||
overflow: auto;
|
||||
width: calc(100% - 31px); /* Abzug von Abständen */
|
||||
max-height: calc(100vh - 37px - 140px - 100px); /* Abzug von Abständen */
|
||||
background-color: hsl( 60, 33%, 95%);
|
||||
border: 1px solid #DDDDDD;
|
||||
border-radius: 4px;
|
||||
}
|
||||
div.content_output ul {
|
||||
margin-left: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
div.content_output li {
|
||||
margin-left: 20px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
/*Pofilgalerie*/
|
||||
ul.galerie {
|
||||
display: block;
|
||||
padding:0px;
|
||||
margin:10px;
|
||||
width:auto;
|
||||
list-style: none;
|
||||
}
|
||||
li.galerie {
|
||||
position: relative;
|
||||
float: left;
|
||||
padding: 0px;
|
||||
margin: 6px;
|
||||
width: 122px;
|
||||
height: auto;
|
||||
border: 1px solid hsl(60, 33%, 50%);
|
||||
border-radius: 6px;
|
||||
/*background-color: #000;*/
|
||||
opacity: 0.9;
|
||||
background: linear-gradient(to top left,
|
||||
hsl(297, 70%, 10%) 0%,
|
||||
hsl(297, 60%, 40%) 30%,
|
||||
hsl(297, 40%, 30%) 60%,
|
||||
hsl(297, 70%, 30%) 100%
|
||||
);
|
||||
}
|
||||
li.galerie:hover {
|
||||
border: 1px solid hsl(60, 33%, 30%);
|
||||
opacity: 1;
|
||||
|
||||
background: linear-gradient(to top left,
|
||||
hsl(297, 70%, 20%) 0%,
|
||||
hsl(297, 60%, 50%) 30%,
|
||||
hsl(297, 40%, 40%) 60%,
|
||||
hsl(297, 70%, 40%) 100%
|
||||
);
|
||||
z-index: 0;
|
||||
}
|
||||
div.galerie_green {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 66px;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-left-radius: 50% 17%;
|
||||
border-bottom-right-radius: 50% 17%;
|
||||
opacity: 1;
|
||||
|
||||
background: radial-gradient(closest-corner at 30% 50%, hsl(146,70%,50%), hsl(146,70%,20%));
|
||||
|
||||
box-shadow: 0 0 2px 1px hsl(146,70%,50%), 0 3px 3px 1px hsl(146,70%,50%,0.7), 0 4px 6px hsl(146,70%,50%,0.5);
|
||||
|
||||
z-index: -3;
|
||||
}
|
||||
div.galerie_red {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 66px;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100%;
|
||||
height: 70%;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-left-radius: 50% 17%;
|
||||
border-bottom-right-radius: 50% 17%;
|
||||
opacity: 1;
|
||||
|
||||
background: radial-gradient(closest-corner at 10% 50%, hsl(360,70%,50%), hsl(360,70%,20%));
|
||||
|
||||
box-shadow: 0 0 2px 1px hsl(360,70%,50%), 0 3px 3px 1px hsl(360,70%,50%,0.7), 0 4px 6px hsl(360,70%,50%,0.5);
|
||||
|
||||
z-index: -3;
|
||||
}
|
||||
img.galerie_image {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border: 0px solid hsl(60, 33%, 60%);
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-left-radius: 50% 17%;
|
||||
border-bottom-right-radius: 50% 17%;
|
||||
|
||||
z-index: -2;
|
||||
}
|
||||
div.galerie_name {
|
||||
display: table;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
text-align: center;
|
||||
font-size: 11pt;
|
||||
font-weight: bold;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* Profildetails
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
div.profil_overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
background-color: hsl(195, 60%, 10%,0.9);
|
||||
z-index: 7;
|
||||
}
|
||||
div.profil_container {
|
||||
display: none;
|
||||
flex-flow: row wrap;
|
||||
justify-content: stretch;
|
||||
align-items: stretch;
|
||||
align-content: center;
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
max-width: 60%;
|
||||
border: 0px solid #DDDDDD;
|
||||
background-color: transparent;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 12px 20px 0 rgba(0, 0, 0, 0.5);
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
div.profil_container a:link {color: hsl(297, 33%, 33%);}
|
||||
div.profil_container a:visited {color: hsl(297, 33%, 33%);}
|
||||
div.profil_container a:hover {color: hsl(297, 50%, 60%);}
|
||||
div.profil_container a:active {color: hsl(297, 50%, 60%);}
|
||||
div.profil_container_bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
backdrop-filter: blur(5px);
|
||||
border-radius: 20px;
|
||||
|
||||
z-index: -2;
|
||||
}
|
||||
.profil_name {
|
||||
margin: 10px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
font-size: 16pt;
|
||||
font-weight: bold;
|
||||
color: hsl(195, 30%, 15%);
|
||||
text-shadow: 1px 1px 2px #888888;
|
||||
}
|
||||
.profil_name_sub {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
color: hsl(297, 50%, 40%);
|
||||
}
|
||||
.profil_exit {
|
||||
display: table;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
|
||||
text-align: center;
|
||||
font-size: 16pt;
|
||||
|
||||
background-color: #FFFFFF;
|
||||
border: 0px solid #DDDDDD;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.2), 0 1px 3px 0 rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.profil_exit:hover {
|
||||
cursor: pointer;
|
||||
background-color: hsl(297, 70%, 40%, 0.7);
|
||||
}
|
||||
div.profil_content_small {
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
width: 250px;
|
||||
text-align: center;
|
||||
|
||||
background-color: #FFFFFF;
|
||||
border: 5px solid hsl(60, 33%, 80%);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.3), 0 3px 6px 0 rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
div.profil_content_small img {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
div.profil_data {
|
||||
-ms-flex: 50%;
|
||||
flex: 50%;
|
||||
padding: 30px;
|
||||
margin: 5px;
|
||||
|
||||
border: 0px solid #DDDDDD;
|
||||
background-color: hsl(60, 33%, 80%);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.3), 0 3px 6px 0 rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
div.profil_data td {
|
||||
padding-top: 2px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
padding-bottom: 2px;
|
||||
margin: 0px;
|
||||
width: auto;
|
||||
|
||||
border-spacing: 0px;
|
||||
border-bottom: 1px solid #AAAAAA;
|
||||
|
||||
}
|
||||
div.profil_calendar {
|
||||
-ms-flex: 50%;
|
||||
flex: 50%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 600px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #DDDDDD;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.3), 0 3px 6px 0 rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* Kalenderblatt*/
|
||||
.page_calendar {
|
||||
position: relative;
|
||||
display: none; /* Ausblenden, wird per Javascript gesteuert */
|
||||
height: calc(100vh - 20px - 2px);
|
||||
max-height: 750px;
|
||||
max-width: 525px;
|
||||
padding: 0px;
|
||||
margin: 5px;
|
||||
background-color: #FEFEFE;
|
||||
border: 1px solid hsl(210, 0%, 90%);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 1px 1px 0 rgba(0, 0, 0, 0.3), 0 3px 6px 0 rgba(0, 0, 0, 0.4);
|
||||
|
||||
aspect-ratio: 7/10;
|
||||
|
||||
/* Bild */
|
||||
/*background-image: url('img/bg_sun.jpg');*/
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
|
||||
}
|
||||
.page_calendar .active { display: flex; }
|
||||
|
||||
.page_calendar button {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
height: 30px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid transparent;
|
||||
background-color: hsl(297, 10%, 95%);
|
||||
z-index: 10;
|
||||
}
|
||||
.page_calendar button:hover {
|
||||
border: 1px solid hsl(297, 40%, 90%);
|
||||
background-color: hsl(297, 80%, 95%);
|
||||
}
|
||||
.calendar_header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 34px;
|
||||
margin: 0px 0px 0px 0px;
|
||||
padding: 5px 5px 5px 5px;
|
||||
background: linear-gradient(to bottom,
|
||||
hsl(210, 57%, 80%) 0%,
|
||||
hsl(210, 57%, 97%) 90%);
|
||||
border: 0px solid #DDDDDD;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
border-top-left-radius: 9px;
|
||||
border-top-right-radius: 9px;
|
||||
}
|
||||
.calendar_title {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
width: 150px;
|
||||
font-size: 14.0pt;
|
||||
text-align: center;
|
||||
}
|
||||
.arrow_item {
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
.arrow_item:hover {
|
||||
border: 1px solid hsla(297, 0%, 50%, 0.5);
|
||||
background-color: hsl(297, 0%, 90%, 0.5);
|
||||
}
|
||||
.arrow_item:hover svg path { fill: hsl(210, 0%, 100%); }
|
||||
.arrow_light svg path { fill: hsl(210, 30%, 70%); }
|
||||
.arrow_dark svg path { fill: hsl(210, 100%, 30%); }
|
||||
|
||||
.calendar_content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: flex-start;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
font-size: 1.0em;
|
||||
font-weight: 600;
|
||||
|
||||
border-spacing: 0px;
|
||||
border: 0px solid #DDDDDD;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.calendar_content table {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* border-spacing: 9px; */
|
||||
}
|
||||
.calendar_content thead {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* border-spacing: 9px; */
|
||||
}
|
||||
.calendar_content table td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
td.calendar_head {
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 2px solid hsl(195, 40%, 70%);
|
||||
}
|
||||
td.calendar_head_sat {
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid hsl(297, 10%, 70%);
|
||||
}
|
||||
td.calendar_head_sun {
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid hsl(297, 80%, 70%);
|
||||
}
|
||||
td.calendar_day_area {
|
||||
align-content: baseline;
|
||||
padding-top: 2px;
|
||||
width: 100%;
|
||||
}
|
||||
td.calendar_day_area:hover {
|
||||
cursor: default;
|
||||
}
|
||||
td.calendar_day_area a {
|
||||
text-decoration: none;
|
||||
}
|
||||
#calendar_day_item:hover, #calendar_day_item *:hover {
|
||||
color: hsl(195, 0%, 90%);
|
||||
background-color: hsl(195, 80%, 60%);
|
||||
box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.calendar_day_item {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
aspect-ratio: 1/1;
|
||||
vertical-align: middle;
|
||||
border-radius: 100%;
|
||||
box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
/*Kombi mit -> calendar_day_item*/
|
||||
.availableday {
|
||||
color: #FFFFFF;
|
||||
background-color: hsl(132, 100%, 27%);
|
||||
}
|
||||
.normalday {
|
||||
background-color: hsl(297, 20%, 100%);
|
||||
}
|
||||
.today {
|
||||
color: #FFFFFF;
|
||||
background-color: hsl(195, 100%, 30%);
|
||||
box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
/*td.today:hover {
|
||||
color: hsl(195, 0%, 90%);
|
||||
background-color: hsl(195, 80%, 60%);
|
||||
box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.3);
|
||||
} */
|
||||
.saturday {
|
||||
color: #FFFFFF;
|
||||
background-color: #555555;
|
||||
}
|
||||
.sunday { /* auch für gesetzliche Feiertage in Berlin */
|
||||
color: #FFFFFF;
|
||||
background-color: hsl(297, 80%, 70%);
|
||||
}
|
||||
.localholiday { /* sonstige regionale Feiertage */
|
||||
background-color: hsl(297, 20%, 70%);
|
||||
}
|
||||
div.calendar_day {
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
height: 60px;
|
||||
border: 0px solid #000;
|
||||
}
|
||||
div.feiertagsname {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
display: flex;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
padding: 0px;
|
||||
margin-top: 0px;
|
||||
font-size: 7.5pt;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
color: hsl(297, 30%, 50%);
|
||||
border: 1px solid hsl(297, 30%, 90%);
|
||||
z-index:5;
|
||||
}
|
||||
|
||||
/* Verfügbarkeit: Kalendertag */
|
||||
td.greenbox {
|
||||
box-shadow: 4px 4px 4px hsl(146,50%,50%),
|
||||
4px -4px 4px hsl(146,70%,30%),
|
||||
-4px 4px 4px hsl(146,30%,70%),
|
||||
-4px -4px 4px hsl(146,50%,30%);
|
||||
}
|
||||
|
||||
@media (max-width: 750px) {
|
||||
#seelsorge.menue .list {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
#seelsorge.menue .menu-item {
|
||||
padding: 5px 2vw 5px 2vw;
|
||||
margin: 1vw;
|
||||
max-width: 24vw;
|
||||
font-size: 80%;
|
||||
}
|
||||
.content_seelsorge {
|
||||
padding: 0px;
|
||||
margin-top: 0px;
|
||||
width: calc(100% - 0px - 0px); /* Abzug von Padding+Border */
|
||||
border: 0px solid #DDDDDD;
|
||||
border-radius: 5px;
|
||||
background-color: transparent;
|
||||
}
|
||||
.page_calendar {
|
||||
width: calc(100vw - 30px - 2px);
|
||||
max-width: 700px;
|
||||
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
@media (max-width: 650px) {
|
||||
.page_calendar {
|
||||
width: calc(100vw - 10px - 2px);
|
||||
|
||||
max-width: 600px;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
@media (max-width: 550px) {
|
||||
.page_calendar {
|
||||
max-height: 550px;
|
||||
max-width: 550px;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
@media (max-width: 475px) {
|
||||
.page_calendar {
|
||||
|
||||
max-height: 475px;
|
||||
max-width: 475px;
|
||||
|
||||
transform: scale(0.6);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php /* Name: template.php
|
||||
Beschreibung: Grundstruktur einer PHP-Seite für das Intranet */
|
||||
|
||||
// Initialisierung
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
|
||||
|
||||
<div class="header_title" id="header_title">
|
||||
<span class="header_title_text">DUMMY-TITEL FÜR INTRANET-SEITE</span>
|
||||
</div>
|
||||
|
||||
<div class="content" id="base"> <!-- alternativ: id="fullwith" -->
|
||||
<div class="content_panel">
|
||||
|
||||
<?php
|
||||
if (isset($_SESSION["user_id"])):
|
||||
?>
|
||||
|
||||
<form class="display_within" style="border:none"method="post" action="">
|
||||
</form>
|
||||
|
||||
|
||||
<?php else:
|
||||
header("Location: $g_httpLoginPath");
|
||||
exit();
|
||||
endif; ?>
|
||||
|
||||
</div> <!-- EOD: content_panel -->
|
||||
</div> <!-- EOD: content -->
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php /* Name: template_admin.php
|
||||
Beschreibung: Grundstruktur einer PHP-Seite für Administratoren */
|
||||
|
||||
// Initialisierung
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<?php // Besondere Admin-Rechte checken
|
||||
// Fetch user details
|
||||
$sql = "SELECT * FROM user_permissions up INNER JOIN user_general_information ugi ON up.user_id = ugi.user_id WHERE up.user_id = {$_SESSION["user_id"]}";
|
||||
$result = $pdo->query($sql);
|
||||
$isAdmin = $result->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// Check if the user has admin access (Admin = 1)
|
||||
if ($isAdmin["Admin"] == 1) {
|
||||
$sql_groups = "SELECT * FROM user_permissions";
|
||||
$stmt = $pdo->prepare($sql_groups);
|
||||
$stmt->execute();
|
||||
$groups = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
} else {
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="header_title" id="header_title">
|
||||
<span class="header_title_text">DUMMY-TITEL FÜR ADMIN-SEITE</span>
|
||||
</div>
|
||||
|
||||
<div class="content" id="base">
|
||||
<div class="content_panel">
|
||||
|
||||
<?php
|
||||
if (isset($_SESSION["user_id"])):
|
||||
?>
|
||||
|
||||
<form class="display_within" style="border:none"method="post" action="">
|
||||
</form>
|
||||
|
||||
|
||||
<?php else:
|
||||
header("Location: $g_httpLoginPath");
|
||||
exit();
|
||||
endif; ?>
|
||||
|
||||
</div> <!-- EOD: content_panel -->
|
||||
</div> <!-- EOD: content -->
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,130 @@
|
||||
# NAK Intranet – Design-Richtlinien
|
||||
## Basierend auf dem CD-Manual NAK 2026
|
||||
|
||||
---
|
||||
|
||||
## 1. Farben (Digital-Palette)
|
||||
|
||||
| Farbe | HEX-Wert | Verwendung |
|
||||
|-----------------|-----------|---------------------------------------|
|
||||
| NAK Blau | `#2786cf` | Primärfarbe, Buttons, Links, Header |
|
||||
| Schwarz | `#000000` | Texte, Icons |
|
||||
| Sonnengelb | `#ffdc0f` | Akzente, Warnungen |
|
||||
| Orange | `#f08200` | Akzente |
|
||||
| Rot | `#d21400` | Fehlermeldungen, Warnstufen |
|
||||
| Himbeere | `#d73282` | Akzente |
|
||||
| Lila | `#731e7d` | Seelsorge-Bereich |
|
||||
| Dunkelblau | `#1243a0` | Akzente |
|
||||
| Türkisblau | `#00a091` | Akzente |
|
||||
| Dunkelgrün | `#006e14` | Entwickler-Bereich, Erfolg |
|
||||
| Gelbgrün | `#82be23` | Akzente |
|
||||
|
||||
### Neutrale Farben (Graustufen)
|
||||
- Hintergrund: `#f8f9fa` (Gray-50)
|
||||
- Karten/Panels: `#ffffff`
|
||||
- Trennlinien: `#e9ecef` (Gray-200)
|
||||
- Sekundärer Text: `#6c757d` (Gray-600)
|
||||
- Primärer Text: `#212529` (Gray-900)
|
||||
|
||||
---
|
||||
|
||||
## 2. Typografie
|
||||
|
||||
- **Hausschrift**: Suisse Int'l (als woff2 eingebunden)
|
||||
- Light (300) – Fließtext
|
||||
- Medium (500) – Überschriften, Labels
|
||||
- Semibold (600) – Buttons, Hervorhebungen
|
||||
- **Fallback**: Arial, sans-serif
|
||||
|
||||
### Schriftgrößen
|
||||
| Token | Größe |
|
||||
|-------------|-----------|
|
||||
| xs | 0.75rem |
|
||||
| sm | 0.875rem |
|
||||
| base | 1rem |
|
||||
| md | 1.125rem |
|
||||
| lg | 1.25rem |
|
||||
| xl | 1.5rem |
|
||||
| 2xl | 2rem |
|
||||
| 3xl | 2.5rem |
|
||||
|
||||
---
|
||||
|
||||
## 3. Formsprache: Eckiges Design
|
||||
|
||||
Das CD-Manual schreibt eine **eckige Formsprache** vor:
|
||||
- **Keine abgerundeten Ecken** (border-radius: 0) für UI-Elemente
|
||||
- Ausnahme: Profilbilder (kreisförmig, border-radius: 50%)
|
||||
- Ausnahme: Pillentags/Badges (border-radius: 9999px)
|
||||
- Klare, geradlinige Kanten
|
||||
- Scharfe Konturen bei Karten, Buttons, Eingabefeldern, Modals
|
||||
|
||||
---
|
||||
|
||||
## 4. Logo – Wort-Bild-Marke
|
||||
|
||||
- Das offizielle NAK-Logo wird immer zusammen mit dem Schriftzug verwendet
|
||||
- Anordnung: Logo-Symbol links, daneben:
|
||||
- Zeile 1: **Neuapostolische Kirche** (Medium, 500)
|
||||
- Zeile 2: *Berlin-Reinickendorf* (Light, 300)
|
||||
- Mindestgröße: Logo-Symbol 44px (Desktop), 36px (Mobile)
|
||||
- Das Logo darf nicht verzerrt, eingefärbt oder manipuliert werden
|
||||
|
||||
---
|
||||
|
||||
## 5. Header
|
||||
|
||||
- Weißer Hintergrund (`#ffffff`)
|
||||
- 3px NAK-Blau-Linie am unteren Rand
|
||||
- Logo + Wordmark links
|
||||
- Profilbild rechts (kreisrund)
|
||||
- **Desktop**: Hover → Name + Abmelden ausfahren
|
||||
- **Mobile**: Klick → Name + Abmelden ausfahren
|
||||
- Sticky mit Hide-on-scroll-down, Show-on-scroll-up
|
||||
|
||||
---
|
||||
|
||||
## 6. Footer
|
||||
|
||||
- Weißer Hintergrund
|
||||
- 2px NAK-Blau-Linie oben
|
||||
- Zentrierte Links: Impressum | Admin kontaktieren | Datenschutz
|
||||
- Kein Release-Marker (entfernt)
|
||||
|
||||
---
|
||||
|
||||
## 7. Hauptmenü (Intranet Startseite)
|
||||
|
||||
- **Desktop**: Volle Bildschirmbreite, Grid-Layout
|
||||
- **Mobile**: Zentriert, angepasstes Grid (2 Spalten)
|
||||
- Buttons: Eckig, mit Schatten, Hover-Effekt (leichte Vergrößerung)
|
||||
- Farbige Buttons gemäß Bereichszugehörigkeit (Blau, Lila, Rot, Schwarz, Grün)
|
||||
|
||||
---
|
||||
|
||||
## 8. Authorization-Seiten (Login, Registrierung, Passwort-Reset)
|
||||
|
||||
- Zentriertes Card-Layout
|
||||
- NAK-Logo mit Wordmark oben
|
||||
- Eckige Eingabefelder
|
||||
- Eckige Buttons (Pillform für primäre Actions beibehalten als Ausnahme)
|
||||
- Hintergrund: Leichter Gradient (Gray-50 → NAK-Blau-Light)
|
||||
|
||||
---
|
||||
|
||||
## 9. Profil-Seiten
|
||||
|
||||
- Zentriertes Layout, max. 600px Breite
|
||||
- Großes, kreisrundes Profilbild mit Hover-Effekt
|
||||
- Eckige Eingabefelder und Karten
|
||||
- Klare Gruppenübersicht
|
||||
|
||||
---
|
||||
|
||||
## 10. Allgemeine Regeln
|
||||
|
||||
- **Schatten**: Dezent, mehrstufig (sm, md, lg, xl)
|
||||
- **Übergänge**: 150ms (schnell), 250ms (standard), 400ms (langsam)
|
||||
- **Abstände**: Konsistentes Spacing-System (0.25rem bis 4rem)
|
||||
- **Responsive**: Mobile-first, Breakpoints bei 480px und 768px
|
||||
- **Barrierefreiheit**: Focus-Styles beibehalten, ausreichender Kontrast
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/runtime_env.php';
|
||||
|
||||
$host = intranet_env('DB_HOST');
|
||||
$port = intranet_env('DB_PORT', '5432');
|
||||
$dbname = intranet_env('DB_NAME');
|
||||
$username = intranet_env('DB_USER');
|
||||
$password = intranet_env('DB_PASSWORD');
|
||||
|
||||
try {
|
||||
$pdo = new PDO(
|
||||
"pgsql:host={$host};port={$port};dbname={$dbname}",
|
||||
$username,
|
||||
$password,
|
||||
[
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
]
|
||||
);
|
||||
} catch (PDOException $e) {
|
||||
error_log('Database connection failed: ' . $e->getMessage());
|
||||
http_response_code(500);
|
||||
exit('Database connection failed.');
|
||||
}
|
||||
|
||||
return $pdo;
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php /* Name: functions.php
|
||||
Beschreibung: Generelle Funktionen
|
||||
- Verwaltung von Schaltflächen
|
||||
- Info-Panels (Boxen und Tabellen)
|
||||
- Markdown-Formatierung
|
||||
- Eigene Prüffunktionen */
|
||||
|
||||
|
||||
|
||||
|
||||
// Schaltfläche: Ausgabe eines beliebigen Buttons
|
||||
function display_button($p_key,$p_text,$align) {
|
||||
|
||||
global $p_buttons;
|
||||
|
||||
if (array_key_exists($p_key, $p_buttons)) {
|
||||
$p_file = $p_buttons[$p_key];
|
||||
|
||||
echo "<div class='button_picto' style='justify-content:" . $align . ";'>";
|
||||
echo file_get_contents($p_file);
|
||||
if ($p_text) echo $p_text;
|
||||
echo "</div>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Infopanel mit einer zweispaltigen Tabelle
|
||||
* @param string $title Überschrift des Panels
|
||||
* @param array $data_array Strukturdaten mit Schlüssel und Wert
|
||||
* @return string Die formatierte Zeichenkette.
|
||||
*/
|
||||
function infopanel_table($title, $data_array) {
|
||||
// Ausgabe des Panels mit ZWEI Spalten
|
||||
echo '<div class="info_panel_table">';
|
||||
echo ' <table>';
|
||||
echo ' <thead>';
|
||||
echo ' <tr>';
|
||||
echo ' <th colspan="2">';
|
||||
echo ' <label>' . $title . '</label>';
|
||||
echo ' </th>';
|
||||
echo ' </tr>';
|
||||
echo '</thead>';
|
||||
echo ' <tbody id="tableBody">';
|
||||
|
||||
foreach ($data_array as $key => $value) {
|
||||
|
||||
echo ' <tr>';
|
||||
echo ' <td>' . $key . '</td>';
|
||||
echo ' <td>' . nvl($value, '---') . '</td>';
|
||||
echo ' </tr>';
|
||||
}
|
||||
echo ' </tbody>';
|
||||
echo ' </table>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
|
||||
/** Markdown-Formatierung für Schnelleingaben
|
||||
* @param string $text Die zu formatierende Zeichenkette.
|
||||
* @return string Die formatierte Zeichenkette.
|
||||
*/
|
||||
function markdownFormat($text) {
|
||||
$text = nl2br(rtrim($text, "\n")); // Umbrüche formatieren (<BR>)
|
||||
|
||||
$pattern = "/(\::::)( .+)/";
|
||||
$replacement = "<li style='margin-left:40px; list-style: none;'>$2</li>"; // :::: {Einrücken 2. Ebene}
|
||||
$text = preg_replace($pattern, $replacement, $text);
|
||||
|
||||
$pattern = "/(\::)( .+)/";
|
||||
$replacement = "<li style='margin-left:20px; list-style: none;'>$2</li>"; // :: {Einrücken 1. Ebene}
|
||||
$text = preg_replace($pattern, $replacement, $text);
|
||||
|
||||
$pattern = "/(\-\-)( .+)/";
|
||||
$replacement = "<li style='margin-left:40px;'>$2</li>"; // -- {Listenelement 2. Ebene}
|
||||
$text = preg_replace($pattern, $replacement, $text);
|
||||
|
||||
$pattern = "/(\-)( .+)/";
|
||||
$replacement = "<li>$2</li>"; // - {Listenelement 1. Ebene}
|
||||
$text = preg_replace($pattern, $replacement, $text);
|
||||
|
||||
$text = preg_replace("/\*\*(.*?)\*\*/s", "<b>$1</b>", $text); // **{Fett}**
|
||||
$text = preg_replace("/\*(.*?)\*/s", "<i>$1</i>", $text); // *{Kursiv}*
|
||||
|
||||
$text = "<ul>" . $text . "</ul>"; // Listenumschluss
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
// EIGENE PRÜFFUNKTIONEN //
|
||||
/////////////////////////////////////////
|
||||
|
||||
|
||||
/** Checken einer Zeichenkette auf das Vorhandensein.
|
||||
* @param string|null $value Die zu überprüfende Zeichenkette.
|
||||
* @param mixed $default Der Ersatzwert, der zurückgegeben wird, wenn die Zeichenkette leer ist.
|
||||
* @return mixed Der ursprüngliche Wert oder der Ersatzwert.
|
||||
*/
|
||||
function nvl(string $value = null, $default) {
|
||||
return isset($value) && $value !== '' ? $value : $default;
|
||||
}
|
||||
|
||||
|
||||
/** Gegenderte Anzeige eines Rollennamens (Datenbankwert → Anzeige).
|
||||
* @param string $role Der Rollenname aus der Datenbank
|
||||
* @return string Der gegenderte Anzeigename
|
||||
*/
|
||||
function genderRole(string $role): string {
|
||||
static $map = [
|
||||
'Admin' => 'Admin',
|
||||
'Technik' => 'Technik',
|
||||
'Entwickler' => 'Entwickler*in',
|
||||
'Amtsgeschwister' => 'Amtsgeschwister',
|
||||
'Diakon' => 'Diakon*in',
|
||||
'DiakonIn' => 'Diakon*in',
|
||||
'Priester' => 'Priester*in',
|
||||
'PriesterIn' => 'Priester*in',
|
||||
'Brandschutz' => 'Brandschutz',
|
||||
'Brandschutzbeauftragter' => 'Brandschutzbeauftrage*r',
|
||||
];
|
||||
return $map[$role] ?? $role;
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php /* Name: parameters.php
|
||||
Beschreibung: Generelle Parameter
|
||||
- inkl. Pfade und Standardbuttons */
|
||||
require_once __DIR__ . '/runtime_env.php';
|
||||
$publicHost = $_SERVER['HTTP_HOST'] ?? intranet_env('INTRANET_FQDN');
|
||||
|
||||
$p_version = "v0.6.0"; // {Release}.{Update}.{Hotfix/Commit}
|
||||
|
||||
|
||||
$p_nac_base = "bln-rd"; // Gemeinde
|
||||
$p_project = "Intranet"; // Systemname des Projekts
|
||||
$p_status = "#dev"; // Entwicklungsstatus: #dev #test #live
|
||||
|
||||
|
||||
// Lokalisierung
|
||||
date_default_timezone_set('Europe/Berlin'); //Mitteleuropäische Zeitzone
|
||||
$g_locale = setlocale(LC_TIME, 'de_DE', 'de_DE.UTF-8'); //Deutsche UTF-8 Kodierung
|
||||
|
||||
|
||||
// Zusammenfassungen von Informationen für Administratoren und Entwickler
|
||||
$array_admin = [
|
||||
'Projekt' => $p_project,
|
||||
'Gemeinde' => $p_nac_base,
|
||||
'Version' => $p_version,
|
||||
'Status' => $p_status,
|
||||
];
|
||||
$array_dev = [
|
||||
'Host' => $_SERVER['HTTP_HOST'],
|
||||
'IPv4-Adresse' => $_SERVER['SERVER_ADDR'],
|
||||
'PHP-Version' => phpversion(),
|
||||
'Server-Software' => $_SERVER['SERVER_SOFTWARE'],
|
||||
'Betriebssystem' => php_uname('s'),
|
||||
'Zeitzone' => date_default_timezone_get(),
|
||||
'Locale-Einstellung' => $g_locale,
|
||||
'Aktivierte PHP-Erweiterungen' => implode(', ', get_loaded_extensions()),
|
||||
'Maximale Upload-Dateigröße' => ini_get('upload_max_filesize'),
|
||||
'Speicherlimit für PHP-Skripte' => ini_get('memory_limit'),
|
||||
];
|
||||
|
||||
|
||||
// Prefixe
|
||||
$isHttps = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on')
|
||||
|| (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
|
||||
&& strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https');
|
||||
$g_httpPrefix = ($isHttps ? 'https' : 'http') . '://';
|
||||
|
||||
// Absolute Pfade
|
||||
$g_generalFilePath = $_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/";
|
||||
$g_projectsPath = $_SERVER['DOCUMENT_ROOT']."/intranet_repo/projects/";
|
||||
|
||||
$g_httpCurrentUrl = $g_httpPrefix.$publicHost.$_SERVER['REQUEST_URI'];
|
||||
$g_httpCurrentCleanUrl = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$g_httpCurrentUrl = $g_httpPrefix.$publicHost.$_SERVER['REQUEST_URI'];
|
||||
$g_httpHomePath = $g_httpPrefix.$publicHost."/intranet_repo/projects/intranet/index.php";
|
||||
$g_httpLoginPath = $g_httpPrefix.$publicHost."/intranet_repo/projects/authorization/login.php";
|
||||
$g_httpLogoutPath = $g_httpPrefix.$publicHost."/intranet_repo/projects/authorization/logout.php";
|
||||
|
||||
|
||||
$g_imagePath = $g_projectsPath."_central/img/";
|
||||
$g_imageButtonPath = $g_projectsPath."_central/img/picto/";
|
||||
$g_phpSnippetsPath = $g_projectsPath."_central/php/snippets/";
|
||||
$g_profilePicturePath = $g_generalFilePath."profile_pictures/";
|
||||
|
||||
// Relative Pfade
|
||||
$g_imageRelativePath = "/intranet_repo/projects/_central/img/";
|
||||
$g_imageButtonRelativePath = "/intranet_repo/projects/_central/img/picto/";
|
||||
$g_profilePictureRelativePath = "/intranet_repo/general_files/profile_pictures/";
|
||||
|
||||
|
||||
// Buttons verwalten (SVG-Grafiken)
|
||||
$p_buttons = array(
|
||||
'add' => $g_imageButtonPath.'add.svg',
|
||||
'arrow_left' => $g_imageButtonPath.'arrow_left.svg',
|
||||
'arrow_right' => $g_imageButtonPath.'arrow_right.svg',
|
||||
'arrow_up' => $g_imageButtonPath.'arrow_up.svg',
|
||||
'cancel' => $g_imageButtonPath.'cancel.svg',
|
||||
'edit' => $g_imageButtonPath.'edit.svg',
|
||||
'calendar' => $g_imageButtonPath.'calendar.svg'
|
||||
);
|
||||
?>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
if (!function_exists('intranet_env')) {
|
||||
function intranet_env(string $name, ?string $default = null): string
|
||||
{
|
||||
$value = getenv($name);
|
||||
if ($value === false || $value === '') {
|
||||
if ($default !== null) {
|
||||
return $default;
|
||||
}
|
||||
throw new RuntimeException("Missing required environment variable: {$name}");
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
/* Name: send_mail.php
|
||||
Beschreibung: Zentrale Mail-Funktion für das Intranet
|
||||
Sendet direkt über SMTP (smtp.strato.de:587 mit STARTTLS)
|
||||
HTML-Template für moderne Darstellung
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/runtime_env.php';
|
||||
|
||||
define('SMTP_HOST', intranet_env('SMTP_HOST', 'smtp.strato.de'));
|
||||
define('SMTP_PORT', (int) intranet_env('SMTP_PORT', '587'));
|
||||
define('SMTP_USER', intranet_env('SMTP_USER'));
|
||||
define('SMTP_PASS', intranet_env('SMTP_PASSWORD'));
|
||||
define('ADMIN_EMAIL', intranet_env('ADMIN_EMAIL', 'technik@nak-reinickendorf.de'));
|
||||
|
||||
/**
|
||||
* Erzeugt das HTML-Template für E-Mails im NAK-Design.
|
||||
*/
|
||||
function build_html_mail(string $betreff, string $inhalt, ?string $buttonText = null, ?string $buttonUrl = null): string {
|
||||
$buttonHtml = '';
|
||||
if ($buttonText && $buttonUrl) {
|
||||
$buttonHtml = '
|
||||
<tr><td style="padding:24px 0 8px 0;" align="center">
|
||||
<a href="' . htmlspecialchars($buttonUrl) . '" style="display:inline-block;padding:14px 32px;background:#2786cf;color:#ffffff;text-decoration:none;font-weight:700;font-size:15px;letter-spacing:0.02em;">
|
||||
' . htmlspecialchars($buttonText) . '
|
||||
</a>
|
||||
</td></tr>';
|
||||
}
|
||||
|
||||
// Inhalt: Zeilenumbrüche in <br> umwandeln, aber vorhandenes HTML beibehalten
|
||||
$inhaltHtml = nl2br(htmlspecialchars($inhalt));
|
||||
|
||||
$datum = date('d.m.Y, H:i') . ' Uhr';
|
||||
|
||||
// Logo-URL dynamisch ermitteln
|
||||
$host = $_SERVER['HTTP_HOST'] ?? intranet_env('INTRANET_FQDN');
|
||||
$logoUrl = 'https://' . $host . '/intranet_repo/projects/_central/img/nak-logo.svg';
|
||||
|
||||
return '<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"></head>
|
||||
<body style="margin:0;padding:0;background-color:#f0f2f5;font-family:-apple-system,BlinkMacSystemFont,\'Segoe UI\',Roboto,Helvetica,Arial,sans-serif;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#f0f2f5;padding:32px 16px;">
|
||||
<tr><td align="center">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="max-width:560px;overflow:hidden;">
|
||||
<!-- Header with Logo + Wordmark -->
|
||||
<tr><td style="background:#ffffff;padding:28px 32px;border-bottom:3px solid #2786cf;" align="left">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0"><tr>
|
||||
<td style="vertical-align:bottom;padding-right:14px;">
|
||||
<img src="' . htmlspecialchars($logoUrl) . '" alt="NAK" width="48" height="48" style="display:block;width:48px;height:48px;">
|
||||
</td>
|
||||
<td style="vertical-align:bottom;line-height:1.2;">
|
||||
<div style="font-size:15px;font-weight:500;color:#1a1a1a;white-space:nowrap;">Neuapostolische Kirche</div>
|
||||
<div style="font-size:12px;font-weight:300;color:#6b7280;white-space:nowrap;">Gemeinde Reinickendorf</div>
|
||||
</td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<!-- Blue title bar -->
|
||||
<tr><td style="background:linear-gradient(135deg,#2786cf,#1e6fad);padding:20px 32px;">
|
||||
<div style="font-size:20px;font-weight:700;color:#ffffff;letter-spacing:-0.01em;">' . htmlspecialchars($betreff) . '</div>
|
||||
</td></tr>
|
||||
<!-- Content -->
|
||||
<tr><td style="background:#ffffff;padding:28px 32px 12px 32px;">
|
||||
<div style="font-size:15px;line-height:1.7;color:#374151;">' . $inhaltHtml . '</div>
|
||||
</td></tr>
|
||||
' . $buttonHtml . '
|
||||
<!-- Footer -->
|
||||
<tr><td style="background:#ffffff;padding:20px 32px 24px 32px;border-top:1px solid #e5e7eb;">
|
||||
<div style="font-size:12px;color:#9ca3af;text-align:center;line-height:1.5;">
|
||||
Gesendet am ' . $datum . '<br>
|
||||
Intranet NAK Reinickendorf · Automatische Benachrichtigung
|
||||
</div>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sendet eine HTML-E-Mail über SMTP.
|
||||
*
|
||||
* @param string $empfaenger Empfänger
|
||||
* @param string $betreff Betreff
|
||||
* @param string $nachricht Klartext-Nachricht (wird ins HTML-Template eingebettet)
|
||||
* @param string|null $cc CC-Adresse
|
||||
* @param string $absender Absender
|
||||
* @param string|null $buttonText Optionaler Button-Text
|
||||
* @param string|null $buttonUrl Optionale Button-URL
|
||||
* @return bool
|
||||
*/
|
||||
function send_intranet_mail(
|
||||
string $empfaenger,
|
||||
string $betreff,
|
||||
string $nachricht,
|
||||
?string $cc = null,
|
||||
string $absender = "intranet@nak-reinickendorf.de",
|
||||
?string $buttonText = null,
|
||||
?string $buttonUrl = null
|
||||
): bool {
|
||||
$htmlBody = build_html_mail($betreff, $nachricht, $buttonText, $buttonUrl);
|
||||
|
||||
// MIME-Header
|
||||
$boundary = 'boundary_' . bin2hex(random_bytes(16));
|
||||
$msgId = '<' . bin2hex(random_bytes(16)) . '@nak-reinickendorf.de>';
|
||||
$headers = "From: Intranet NAK Reinickendorf <{$absender}>\r\n";
|
||||
$headers .= "Reply-To: {$absender}\r\n";
|
||||
$headers .= "To: {$empfaenger}\r\n";
|
||||
if (!empty($cc)) {
|
||||
$headers .= "Cc: {$cc}\r\n";
|
||||
}
|
||||
$headers .= "Subject: =?UTF-8?B?" . base64_encode($betreff) . "?=\r\n";
|
||||
$headers .= "Message-ID: {$msgId}\r\n";
|
||||
$headers .= "MIME-Version: 1.0\r\n";
|
||||
$headers .= "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n";
|
||||
$headers .= "X-Mailer: Intranet-NAK-Reinickendorf/1.0\r\n";
|
||||
$headers .= "Date: " . date('r') . "\r\n";
|
||||
|
||||
// Plaintext-Fallback
|
||||
$plainBody = strip_tags($nachricht);
|
||||
|
||||
// Multipart Body
|
||||
$body = "--{$boundary}\r\n";
|
||||
$body .= "Content-Type: text/plain; charset=utf-8\r\n";
|
||||
$body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
|
||||
$body .= $plainBody . "\r\n\r\n";
|
||||
$body .= "--{$boundary}\r\n";
|
||||
$body .= "Content-Type: text/html; charset=utf-8\r\n";
|
||||
$body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
|
||||
$body .= $htmlBody . "\r\n\r\n";
|
||||
$body .= "--{$boundary}--\r\n";
|
||||
|
||||
$message = $headers . "\r\n" . $body;
|
||||
|
||||
$recipients = [$empfaenger];
|
||||
if (!empty($cc)) {
|
||||
$recipients[] = $cc;
|
||||
}
|
||||
|
||||
return smtp_send(SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, $absender, $recipients, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Direkter SMTP-Versand mit STARTTLS und AUTH LOGIN.
|
||||
*/
|
||||
function smtp_send(string $host, int $port, string $user, string $pass, string $from, array $to, string $data): bool {
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
$socket = @stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, 30);
|
||||
if (!$socket) {
|
||||
error_log("SMTP connect failed: {$errstr} ({$errno})");
|
||||
return false;
|
||||
}
|
||||
stream_set_timeout($socket, 30);
|
||||
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '220') { fclose($socket); return false; }
|
||||
|
||||
smtp_write($socket, "EHLO " . gethostname());
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '250') { fclose($socket); return false; }
|
||||
|
||||
smtp_write($socket, "STARTTLS");
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '220') { fclose($socket); return false; }
|
||||
|
||||
$crypto = stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT);
|
||||
if (!$crypto) {
|
||||
error_log("SMTP STARTTLS failed");
|
||||
fclose($socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
smtp_write($socket, "EHLO " . gethostname());
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '250') { fclose($socket); return false; }
|
||||
|
||||
smtp_write($socket, "AUTH LOGIN");
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '334') { fclose($socket); return false; }
|
||||
|
||||
smtp_write($socket, base64_encode($user));
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '334') { fclose($socket); return false; }
|
||||
|
||||
smtp_write($socket, base64_encode($pass));
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '235') {
|
||||
error_log("SMTP auth failed: {$response}");
|
||||
fclose($socket);
|
||||
return false;
|
||||
}
|
||||
|
||||
smtp_write($socket, "MAIL FROM:<{$from}>");
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '250') { fclose($socket); return false; }
|
||||
|
||||
foreach ($to as $recipient) {
|
||||
smtp_write($socket, "RCPT TO:<{$recipient}>");
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '250') { fclose($socket); return false; }
|
||||
}
|
||||
|
||||
smtp_write($socket, "DATA");
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '354') { fclose($socket); return false; }
|
||||
|
||||
$data = str_replace("\r\n.", "\r\n..", $data);
|
||||
fwrite($socket, $data . "\r\n.\r\n");
|
||||
$response = smtp_read($socket);
|
||||
if (substr($response, 0, 3) !== '250') { fclose($socket); return false; }
|
||||
|
||||
smtp_write($socket, "QUIT");
|
||||
smtp_read($socket);
|
||||
fclose($socket);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function smtp_write($socket, string $cmd): void {
|
||||
fwrite($socket, $cmd . "\r\n");
|
||||
}
|
||||
|
||||
function smtp_read($socket): string {
|
||||
$response = '';
|
||||
while ($line = fgets($socket, 512)) {
|
||||
$response .= $line;
|
||||
if (isset($line[3]) && $line[3] === ' ') break;
|
||||
if (strlen($line) < 4) break;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt alle E-Mail-Adressen von Nutzern, die BEIDE angegebenen Rollen besitzen.
|
||||
* Benötigt eine bestehende $pdo-Verbindung.
|
||||
*
|
||||
* @param PDO $pdo Datenbankverbindung
|
||||
* @param array $roles Array von Rollennamen, die alle erfüllt sein müssen
|
||||
* @return array Liste der E-Mail-Adressen
|
||||
*/
|
||||
function get_emails_by_roles(PDO $pdo, array $roles): array {
|
||||
if (empty($roles)) return [];
|
||||
|
||||
$conditions = [];
|
||||
foreach ($roles as $role) {
|
||||
$conditions[] = '"' . str_replace('"', '""', $role) . '" = 1';
|
||||
}
|
||||
$where = implode(' AND ', $conditions);
|
||||
|
||||
$sql = "SELECT ugi.mail FROM user_permissions up
|
||||
INNER JOIN user_general_information ugi ON up.user_id = ugi.user_id
|
||||
WHERE {$where} AND ugi.mail IS NOT NULL AND ugi.mail != ''";
|
||||
$result = $pdo->query($sql);
|
||||
$emails = [];
|
||||
if ($result) {
|
||||
while ($row = $result->fetch()) {
|
||||
$emails[] = $row['mail'];
|
||||
}
|
||||
}
|
||||
return $emails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sendet eine Mail an alle Nutzer mit den Rollen Admin UND Technik (Sammelmail).
|
||||
*
|
||||
* @param PDO $pdo Datenbankverbindung
|
||||
* @param string $betreff Betreff
|
||||
* @param string $nachricht Nachricht
|
||||
* @param string|null $buttonText Optionaler Button-Text
|
||||
* @param string|null $buttonUrl Optionale Button-URL
|
||||
* @return bool True wenn mindestens eine Mail gesendet wurde
|
||||
*/
|
||||
function send_admin_team_mail(
|
||||
PDO $pdo,
|
||||
string $betreff,
|
||||
string $nachricht,
|
||||
?string $buttonText = null,
|
||||
?string $buttonUrl = null
|
||||
): bool {
|
||||
$emails = get_emails_by_roles($pdo, ['Admin', 'Technik']);
|
||||
if (empty($emails)) {
|
||||
// Fallback auf ADMIN_EMAIL
|
||||
return send_intranet_mail(ADMIN_EMAIL, $betreff, $nachricht, null, "intranet@nak-reinickendorf.de", $buttonText, $buttonUrl);
|
||||
}
|
||||
$success = false;
|
||||
foreach ($emails as $email) {
|
||||
if (send_intranet_mail($email, $betreff, $nachricht, null, "intranet@nak-reinickendorf.de", $buttonText, $buttonUrl)) {
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sendet eine Mail an alle Nutzer mit der Rolle Brandschutzbeauftragter.
|
||||
*
|
||||
* @param PDO $pdo Datenbankverbindung
|
||||
* @param string $betreff Betreff
|
||||
* @param string $nachricht Nachricht
|
||||
* @param string|null $buttonText Optionaler Button-Text
|
||||
* @param string|null $buttonUrl Optionale Button-URL
|
||||
* @return bool True wenn mindestens eine Mail gesendet wurde
|
||||
*/
|
||||
function send_brandschutzbeauftragter_mail(
|
||||
PDO $pdo,
|
||||
string $betreff,
|
||||
string $nachricht,
|
||||
?string $buttonText = null,
|
||||
?string $buttonUrl = null
|
||||
): bool {
|
||||
$emails = get_emails_by_roles($pdo, ['Brandschutzbeauftragter']);
|
||||
if (empty($emails)) return false;
|
||||
$success = false;
|
||||
foreach ($emails as $email) {
|
||||
if (send_intranet_mail($email, $betreff, $nachricht, null, "intranet@nak-reinickendorf.de", $buttonText, $buttonUrl)) {
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php /* Name: initialise.php
|
||||
Beschreibung: Initialisierung der grundlegenden Verarbeitungen
|
||||
für die Seiten des Intranets (1. Aufruf)
|
||||
(Ausgenommen davon sind die An-/Abmeldung und Registrierung)
|
||||
|
||||
Ladung: Session, Parameter, Funktionen,
|
||||
Datenbankverbindung und Authentifizierung des Nutzers */
|
||||
|
||||
|
||||
// Session
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
|
||||
// Parameter und Funktionen
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/functions.php';
|
||||
|
||||
|
||||
// Datenbankverbindung
|
||||
if (isset($_SESSION["user_id"])) {
|
||||
|
||||
// Include database connection file
|
||||
$pdo = require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM user_general_information WHERE user_id = ?");
|
||||
$stmt->execute([$_SESSION["user_id"]]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
// Authentication
|
||||
if (isset($user["mail"])) {
|
||||
$stmt_groups = $pdo->prepare("SELECT * FROM user_permissions WHERE user_id = ?");
|
||||
$stmt_groups->execute([$_SESSION["user_id"]]);
|
||||
$groups = $stmt_groups->fetch();
|
||||
}
|
||||
|
||||
} else {
|
||||
header("Location: {$g_httpLoginPath}");
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 299 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 327 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="5058.3882"
|
||||
viewBox="0 0 5058.3882 766.70679"
|
||||
enable-background="new 0 0 5200 800"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="intranet.svg"
|
||||
height="766.70679"
|
||||
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs1" />
|
||||
<sodipodi:namedview
|
||||
id="namedview25"
|
||||
pagecolor="#f1f2f4"
|
||||
bordercolor="#000000"
|
||||
borderopacity="1"
|
||||
showgrid="false"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="0.052980769"
|
||||
inkscape:cx="-764.42831"
|
||||
inkscape:cy="-934.30127"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1358"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg" />
|
||||
<style
|
||||
id="style1">path { fill: #f1f2f4; opacity="1" stroke="none" style="display:inline"}</style>
|
||||
<path
|
||||
id="1_i"
|
||||
d="m 55.846921,280.65323 c -0.785523,160.7849 1.212471,321.0364 6.316604,482.0026 -10.618347,0 -20.714839,0 -30.811332,0 -9.993119,0 -19.986239,0 -31.226396,0 C 11.316134,508.41933 15.377435,254.38003 0,0 21.078011,0 41.14803,0 60.747296,0 59.11366,93.408 57.480641,186.7806 55.846921,280.65323 Z" />
|
||||
<path
|
||||
id="2_n"
|
||||
d="m 263.94938,455.03133 c -0.094,102.7806 -2.31018,205.0743 2.11413,307.6643 -17.28564,0 -34.04425,0 -51.74792,0 11.72375,-253.883 14.63104,-507.8318 -0.0664,-762.2574 1.96695,-0.1725 3.37747,-0.4015 4.78839,-0.4039 15.4993,-0.026 30.99961,-0.095 46.49674,0.09 1.79605,0.021 4.29101,1.0033 5.25723,2.3834 29.33283,41.8961 58.50794,83.9026 87.72083,125.8828 88.01974,126.4882 176.68716,252.5439 260.47421,381.9064 30.3267,46.8228 58.979,94.7306 88.3378,142.1788 2.9187,4.7172 5.4344,9.6837 8.1371,14.5346 0.4771,-0.084 0.9542,-0.1676 1.4313,-0.2513 0,-1.8538 0.051,-3.7093 -0.01,-5.5612 -1.3987,-43.9697 -3.1534,-87.9316 -4.1195,-131.9107 -0.9443,-42.9836 -1.3427,-85.9837 -1.5278,-128.9785 -0.4152,-96.4939 -0.363,-192.99 -0.8986,-289.483 -0.1895,-34.1557 -1.5371,-68.305 -2.3427,-102.4575 -0.059,-2.4917 -0.01,-4.9859 -0.01,-7.9146 16.9793,0 33.8638,0 50.7475,0 -8.1759,253.8841 -9.1391,507.8516 0.09,762.4987 -10.439,0 -21.2036,0.1765 -31.9487,-0.2031 -1.4963,-0.053 -3.172,-2.6637 -4.2991,-4.3938 -21.73,-33.3585 -43.6975,-66.5681 -65.0128,-100.1909 -84.3111,-132.9982 -173.89784,-262.4539 -262.97652,-392.2553 -39.96744,-58.2388 -79.65716,-116.6683 -119.39981,-175.0609 -3.8371,-5.6378 -7.14658,-11.634 -10.72168,-17.4512 -0.73645,-1.1983 -1.56519,-2.3399 -3.27585,-3.3485 3.66208,128.2398 4.84033,256.3529 2.76215,384.9832 z" />
|
||||
<path
|
||||
id="3_t"
|
||||
d="m 1383.2471,45.7185 c -50.642,-0.8569 -100.7924,-1.7344 -150.9444,-2.5139 -9.1775,-0.1426 -8.562,-1.4584 -8.9499,8.4 -4.6272,117.5814 -6.1254,235.21883 -5.1343,352.87233 0.8647,102.6436 2.7607,205.2785 4.1234,307.9183 0.2186,16.473 0.031,32.9515 0.031,49.8292 -18.988,0 -39.025,0 -58.7251,0 0,-9.6737 -0.2366,-19.2759 0.037,-28.8634 2.1898,-76.6167 5.2717,-153.2178 6.513,-229.8489 1.2874,-79.468 1.6011,-158.9717 0.8603,-238.4459 -0.5403,-57.96713 -3.4699,-115.91223 -5.3622,-173.86623 -0.4622,-14.1552 -1.1482,-28.3041 -1.4823,-42.4618 -0.098,-4.1707 -1.2757,-5.7989 -5.7866,-5.6855 -43.9765,1.1051 -87.9588,1.9644 -131.9378,2.9721 -37.31584,0.855 -74.62925,1.8169 -111.94445,2.7077 -1.1154,0.027 -2.2374,-0.2138 -3.6374,-0.3589 0,-16.1464 0,-32.0675 0,-48.3736 188.52605,0 376.89005,0 565.92395,0 -0.7413,15.745 -1.4809,31.4546 -2.2509,47.8118 -30.601,-0.7008 -60.7217,-1.3905 -91.3332,-2.0933 z" />
|
||||
<path
|
||||
id="4_r"
|
||||
d="m 1693.066,762.82672 c -0.7055,1.5411 -1.4462,3.6166 -2.205,3.6232 -20.2795,0.1767 -40.561,0.1407 -61.944,0.1407 15.0303,-254.4632 17.6845,-508.3694 2.6879,-762.98801 2.3573,0 4.1279,0.028 5.8975,0 65.3069,-1.1859 130.6113,-2.5171 195.921,-3.5202 45.6857,-0.7017 90.89,2.9055 134.6044,17.4884 30.7028,10.2424 58.0708,25.8477 79.4777,50.6849 19.125,22.1897 30.1187,48.1807 34.6248,76.878 7.3323,46.6937 3.1809,92.11211 -17.7588,135.03271 -19.3518,39.6654 -49.6182,69.4095 -87.0791,92.004 -11.0918,6.6899 -22.9963,12.0273 -34.4651,18.1044 -1.2696,0.6729 -2.1201,2.1372 -3.1651,3.2344 0.9088,0.7843 1.6939,1.9721 2.7445,2.2944 36.1333,11.0854 63.6491,34.041 86.894,62.9085 19.6672,24.4246 34.4917,51.813 48.4719,79.6813 35.5154,70.7976 64.3426,144.4186 91.9143,218.5624 1.0901,2.9319 2.1233,5.8851 3.481,9.6554 -4.3962,0 -8.1399,0 -11.8838,0 -11.9995,0 -24.0019,-0.1566 -35.9963,0.092 -3.7735,0.078 -5.4329,-1.1069 -6.7889,-4.6875 -23.8288,-62.9311 -49.8635,-124.9229 -79.7014,-185.2701 -15.07,-30.4794 -31.0022,-60.4575 -50.9167,-88.1612 -17.3465,-24.1305 -40.2879,-41.3755 -66.3296,-54.9509 -16.0514,-8.3675 -33.5768,-10.739 -51.2111,-11.9236 -60.4316,-4.0596 -120.9238,-2.3967 -181.4035,-1.2929 -0.818,0.015 -1.6336,0.18 -3.2119,0.3637 0,1.7754 -0.019,3.5351 0,5.2943 1.0211,82.6516 1.7776,165.3077 3.2138,247.9521 0.5122,29.4727 2.6728,58.9167 4.1247,88.8036 m -8.2547,-715.70671 c -0.3651,2.015 -1.081,4.0366 -1.0428,6.0439 0.5898,30.9884 1.8343,61.975 1.8316,92.9618 -0.01,73.99691 -0.5904,147.99381 -0.9398,221.99061 -0.01,2.0834 0,4.1669 0,7.4907 8.4679,0 16.1119,0 23.7561,7e-4 31.4994,0.02 63.0038,0.3861 94.4965,-0.065 18.6283,-0.2666 37.338,-0.928 55.8349,-2.9912 34.8654,-3.8887 67.622,-14.6499 97.1828,-33.9769 31.875,-20.84 55.9978,-48.1322 68.4575,-84.6419 10.281,-30.1245 11.4106,-61.01651 6.5383,-92.26621 -7.3345,-47.0424 -32.3579,-80.0179 -77.2124,-97.3932 -32.8736,-12.7342 -67.2872,-17.6183 -102.1238,-19.4808 -55.3125,-2.9572 -110.6172,-1.0149 -166.7777,2.3271 z" />
|
||||
<path
|
||||
id="5_a"
|
||||
d="m 2327.7505,752.85213 c 19.2041,-45.4364 37.4165,-90.8864 57.5408,-135.4733 54.7898,-121.3885 110.5935,-242.3189 165.5835,-363.6176 30.3787,-67.01033 60.198,-134.28313 86.1362,-203.18563 3.1062,-8.2519 6.0257,-16.5901 8.6145,-25.0164 2.5359,-8.2529 4.5389,-16.6696 6.9214,-25.5592 21.1829,0 43.064,0 64.2639,0 17.3108,61.5161 43.5442,119.3058 69.3809,177.1244 53.384,119.46383 108.0369,238.35983 161.8311,357.64143 28.3308,62.8204 56.5305,125.719 80.7556,190.2853 3.8511,10.2639 6.7737,20.8787 10.0288,31.3614 0.53,1.7069 0.5525,3.5715 0.8721,5.8006 -20.2281,0 -40.1001,0 -59.3702,0 -13.7429,-62.2083 -39.8989,-119.74 -63.768,-178.0492 -13.052,-31.8849 -27.1612,-63.336 -40.6372,-95.0493 -1.4331,-3.3725 -3.0796,-4.7511 -6.9056,-4.7478 -124.3234,0.1053 -248.6472,0.09 -372.9707,0.07 -2.7417,-5e-4 -4.9179,-0.01 -6.3181,3.3023 -29.9043,70.669 -60.5156,141.0623 -85.6504,213.6276 -5.9753,17.2508 -10.1294,35.1353 -15.0029,52.761 -0.6965,2.5188 -0.7229,5.2229 -1.0989,8.147 -20.7207,0 -41.302,0 -62.7038,0 0.8281,-3.1485 1.603,-6.0952 2.497,-9.4221 m 276.5979,-525.8677 c -32.832,72.7061 -65.664,145.4123 -98.6044,218.3583 116.7929,0 232.8803,0 349.3957,0 -0.6238,-1.7314 -1.0427,-3.139 -1.6248,-4.4756 -39.3452,-90.357 -78.6225,-180.7436 -118.0979,-271.04363 -17.6528,-40.3805 -37.3188,-79.9036 -51.6972,-121.8717 -2.7461,-1.0229 -4.2273,0.01 -5.0967,3.1074 -1.3469,4.7975 -2.8616,9.592 -4.821,14.1669 -23.0066,53.7071 -46.1097,107.3729 -69.4537,161.75833 z" />
|
||||
<path
|
||||
id="6_n"
|
||||
d="m 3241.2241,675.02045 c 0.6673,29.4491 1.3304,58.3981 2.0013,87.6769 -16.9424,0 -33.701,0 -51.4034,0 11.7352,-253.8879 14.6209,-507.8365 -0.057,-762.26152 1.9609,-0.1712 3.372,-0.3992 4.7834,-0.4015 15.4993,-0.026 30.9998,-0.095 46.4968,0.09 1.7954,0.021 4.2896,1.005 5.2561,2.3853 29.333,41.896 58.5081,83.9025 87.7207,125.8825 88.0191,126.48822 176.6868,252.54332 260.4734,381.90562 30.3267,46.8226 58.979,94.7303 88.3377,142.1783 2.9184,4.717 5.4338,9.6833 8.1365,14.5339 0.477,-0.084 0.9543,-0.16751 1.4313,-0.2513 0,-1.8539 0.052,-3.7095 -0.01,-5.5616 -1.3989,-43.9696 -3.1499,-87.9314 -4.1208,-131.9104 -0.9419,-42.6501 -1.3448,-85.3168 -1.5264,-127.9782 -0.4116,-96.6604 -0.3533,-193.32302 -0.8872,-289.98242 -0.1897,-34.3223 -1.5447,-68.6381 -2.354,-102.9572 -0.059,-2.4919 -0.01,-4.9864 -0.01,-7.9151 16.9785,0 33.863,0 50.7471,0 -8.1768,253.88292 -9.1368,507.84992 0.089,762.49881 -10.436,0 -21.2007,0.17651 -31.9455,-0.203 -1.4964,-0.053 -3.1731,-2.6624 -4.2999,-4.3922 -21.7307,-33.35829 -43.698,-66.56799 -65.0134,-100.19069 -84.3152,-132.9974 -173.8948,-262.4575 -262.9819,-392.2526 -39.5003,-57.54982 -78.7505,-115.27102 -118.032,-172.97042 -4.3061,-6.3253 -8.0596,-13.0268 -12.0869,-19.5428 -0.7402,-1.1976 -1.5667,-2.342 -3.5991,-3.2771 -0.089,1.8293 -0.2928,3.6614 -0.2495,5.4876 1.0673,44.9812 2.7861,89.9574 3.1115,134.94372 0.5664,78.3216 0.3504,156.6495 0.325,234.9747 -0.025,76.3304 -0.2212,152.6607 -0.3382,229.49099 z" />
|
||||
<path
|
||||
id="7_e"
|
||||
d="m 4126.4746,718.67753 c 71.4199,-2.2664 142.3417,-4.5288 214.061,-6.8168 -0.7451,16.4174 -1.5098,33.2761 -2.2896,50.4655 -150.0732,0 -299.7773,0 -449.3708,0 0,-9.0219 -0.2398,-17.8086 0.043,-26.5785 1.0991,-34.1419 2.4472,-68.2758 3.5473,-102.4177 1.9158,-59.4573 4.5193,-118.9072 5.3506,-178.381 0.9199,-65.8076 0.7197,-131.6446 -0.034,-197.457 -0.5263,-45.9768 -2.6347,-91.93993 -4.3493,-137.89753 -1.4288,-38.2954 -3.3152,-76.5737 -4.9873,-114.8601 -0.064,-1.4648 -0.01,-2.9348 -0.01,-4.7344 138.3159,0 276.373,0 415.1914,0 -0.7642,15.7183 -1.521,31.2789 -2.314,47.5817 -2.6108,0 -5.0278,0.027 -7.4439,0 -114.8071,-1.4635 -229.6137,-2.946 -344.4211,-4.3742 -9.5456,-0.1187 -8.282,-0.8195 -8.2141,8.2124 0.7046,93.8221 1.4219,187.64413 2.1331,281.46623 0.018,2.3219 0,4.6441 0,7.8306 96.0235,-0.3875 191.7266,-1.1139 287.7359,-7.079 0,17.5543 0,34.787 0,51.832 -95.5908,-1.947 -191.2661,-3.8957 -287.7454,-5.8608 0.2673,114.2965 -1.0813,227.1922 2.9629,341.1996 60.1511,-0.7109 119.9011,-1.4171 180.1502,-2.1271 z" />
|
||||
<path
|
||||
id="8_t"
|
||||
d="m 4643.8493,0.005 c 138.2856,0 276.0713,0 414.5386,0 -0.7608,16.1367 -1.501,31.8451 -2.2613,47.9687 -2.6269,0 -4.7666,0.035 -6.9052,-0.01 -78.6382,-1.466 -157.2764,-2.9459 -235.9146,-4.4006 -8.1318,-0.1504 -8.1011,-0.082 -8.4204,7.9567 -5.8862,148.0727 -6.2427,296.21243 -4.646,444.35493 0.9448,87.642 3.2334,175.2695 4.9151,262.9035 0.022,1.1504 0,2.3017 0,3.8394 -20.2554,0 -40.292,0 -59.9736,0 0,-9.7037 -0.2476,-19.3086 0.039,-28.8974 1.8487,-61.7897 3.9976,-123.5708 5.6973,-185.3643 2.5986,-94.4601 3.6372,-188.9431 1.8257,-283.4266 -0.9419,-49.1413 -2.9234,-98.26313 -4.52,-147.39093 -0.7364,-22.648 -1.7842,-45.2863 -2.4356,-67.9363 -0.1338,-4.647 -1.436,-6.2972 -6.3467,-6.1719 -57.6347,1.4701 -115.2749,2.7291 -172.9135,4.0528 -23.4888,0.5394 -46.9776,1.1033 -70.4664,1.6419 -0.9853,0.023 -1.9736,-0.099 -3.4404,-0.1796 0,-16.1404 0,-32.1629 0,-48.9453 50.2334,0 100.4795,0 151.2256,0 z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,865 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" version="1.1" viewBox="0 0 566.929 566.929">
|
||||
<!-- Generator: Adobe Illustrator 29.8.2, SVG Export Plug-In . SVG Version: 2.1.1 Build 3) -->
|
||||
<rect x="0" y="-.006" width="566.93" height="566.94" fill="#2786cf"/>
|
||||
<path d="M198.546,432.37c-.147,0-.308-.03-.469-.049l-71.276-10.782c-1.709-.253-2.867-1.855-2.618-3.554.254-1.68,1.783-2.832,3.55-2.608l71.281,10.791c1.7.254,2.862,1.846,2.608,3.545-.235,1.534-1.568,2.657-3.076,2.657h0ZM372.855,432.155c-1.523,0-2.851-1.114-3.066-2.657-.254-1.699.918-3.281,2.597-3.535l71.306-10.576c1.758-.215,3.281.928,3.516,2.617.253,1.7-.918,3.291-2.598,3.545l-71.306,10.567c-.156.029-.293.039-.449.039h0ZM202.804,405.339c-.459,0-.928-.107-1.373-.322l-84.855-41.609c-1.538-.742-2.178-2.617-1.421-4.16.742-1.543,2.632-2.188,4.16-1.426l84.856,41.609c1.538.752,2.182,2.608,1.421,4.17-.528,1.094-1.646,1.738-2.788,1.738h0ZM368.637,405.134c-1.162,0-2.256-.644-2.802-1.738-.743-1.563-.098-3.418,1.445-4.17l84.841-41.404c1.543-.742,3.398-.108,4.17,1.426.722,1.543.097,3.418-1.455,4.16l-84.831,41.404c-.43.215-.899.322-1.368.322h0ZM215.05,380.995c-.747,0-1.504-.264-2.1-.811l-84.894-77.8c-1.255-1.162-1.348-3.134-.186-4.394,1.167-1.26,3.135-1.338,4.395-.196l84.884,77.79c1.27,1.172,1.358,3.155.196,4.405-.611.674-1.456,1.006-2.295,1.006h0ZM356.372,380.926c-.84,0-1.68-.332-2.285-1.006-1.172-1.269-1.094-3.222.195-4.394l84.899-77.722c1.25-1.152,3.223-1.074,4.375.196,1.172,1.259,1.094,3.232-.195,4.394l-84.899,77.722c-.586.547-1.348.81-2.09.81h0ZM234.15,361.748c-1.045,0-2.075-.547-2.661-1.495l-68.63-112.583c-.888-1.485-.429-3.399,1.026-4.278,1.469-.898,3.398-.439,4.287,1.035l68.634,112.565c.899,1.465.43,3.398-1.035,4.297-.508.293-1.064.459-1.621.459h0ZM337.174,361.601c-.567,0-1.094-.156-1.622-.459-1.464-.889-1.914-2.812-1.035-4.287l68.767-112.418c.898-1.474,2.832-1.924,4.277-1.025,1.465.879,1.934,2.802,1.035,4.267l-68.766,112.428c-.586.967-1.621,1.494-2.656,1.494h0ZM313.083,349.111c-.274,0-.547-.029-.84-.117-1.641-.469-2.617-2.178-2.149-3.819l38.299-137.314c.469-1.646,2.158-2.627,3.877-2.153,1.621.464,2.598,2.173,2.129,3.828l-38.299,137.299c-.39,1.368-1.64,2.276-3.017,2.276h0ZM258.514,349.101c-1.357,0-2.607-.898-2.998-2.266l-38.504-137.309c-.458-1.655.503-3.364,2.159-3.828,1.689-.484,3.369.503,3.838,2.158l38.503,137.3c.459,1.65-.507,3.359-2.158,3.828-.283.088-.576.117-.84.117h0Z" fill="#fff"/>
|
||||
<path d="M297.624,445.094h-23.837c-2.344,0-4.248-1.904-4.248-4.248V138.959h-73.664c-2.334,0-4.238-1.924-4.238-4.283v-24.085c0-2.344,1.904-4.253,4.238-4.253h73.644l.01-55.14c0-2.344,1.904-4.253,4.258-4.253h23.856c2.364,0,4.239,1.909,4.239,4.253v55.14h73.649c2.353,0,4.267,1.909,4.267,4.253v24.085c0,2.359-1.914,4.283-4.267,4.283l-73.649-.015v301.902c0,2.344-1.895,4.248-4.258,4.248h0ZM275.75,438.893h19.93V136.971c0-2.343,1.924-4.248,4.327-4.248l73.571.015v-20.18h-73.63c-2.363,0-4.268-1.904-4.268-4.248v-55.144h-19.94l-.01,55.144c0,2.344-1.894,4.248-4.219,4.248h-73.668v20.18h73.649c2.363,0,4.258,1.89,4.258,4.219v301.936h0Z" fill="#fff"/>
|
||||
<path d="M396.009,475.873l-41.003.127c-1.875,2.754-3.946,5.381-6.163,7.911h-126.206c-2.275-2.618-4.438-5.352-6.264-8.047l-40.706.009c-3.936,0-7.124,3.184-7.124,7.12s3.188,7.119,7.124,7.119l36.395-.049c.142.019.288.049.43.049h183.518c3.926,0,7.139-3.184,7.139-7.1,0-3.955-3.213-7.139-7.139-7.139Z" fill="#fff"/>
|
||||
<path d="M249.921,504.603h-29.926c-3.936,0-7.144,3.164-7.144,7.109,0,1.905.738,3.692,2.08,5.039,1.353,1.338,3.145,2.11,5.064,2.11h131.513c1.915,0,3.711-.772,5.059-2.11,1.328-1.347,2.07-3.134,2.07-5.039,0-3.945-3.183-7.109-7.129-7.109h-29.959c-10.85,5.137-22.988,8.008-35.82,8.008s-24.94-2.871-35.809-8.008Z" fill="#fff"/>
|
||||
<path d="M420.501,447.106h-53.045c-.606,2.676-1.348,5.371-2.188,8.027h-158.978c-.933-2.676-1.758-5.4-2.344-8.027h-52.908c-3.931,0-7.119,3.203-7.119,7.129s3.188,7.129,7.119,7.129l54.651-.02h157.314v.01l57.498.01c3.935,0,7.138-3.194,7.138-7.129s-3.203-7.129-7.138-7.129Z" fill="#fff"/>
|
||||
<metadata>
|
||||
<i:aipgfRef id="adobe_illustrator_pgf"/>
|
||||
<i:aipgf id="adobe_illustrator_pgf" i:pgfEncoding="zstd/base64" i:pgfVersion="24">
|
||||
<![CDATA[
|
||||
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
|
||||
]]>
|
||||
</i:aipgf>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 68 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" ?><svg id="plus-add-more-detail" style="enable-background:new 0 0 15 15;" version="1.1" viewBox="0 0 15 15" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M7.5,0C3.364,0,0,3.364,0,7.5S3.364,15,7.5,15S15,11.636,15,7.5S11.636,0,7.5,0z M7.5,14C3.916,14,1,11.084,1,7.5 S3.916,1,7.5,1S14,3.916,14,7.5S11.084,14,7.5,14z"/><polygon points="8,3.5 7,3.5 7,7 3.5,7 3.5,8 7,8 7,11.5 8,11.5 8,8 11.5,8 11.5,7 8,7 "/></svg>
|
||||
|
After Width: | Height: | Size: 492 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.2893 5.70708C13.8988 5.31655 13.2657 5.31655 12.8751 5.70708L7.98768 10.5993C7.20729 11.3805 7.2076 12.6463 7.98837 13.427L12.8787 18.3174C13.2693 18.7079 13.9024 18.7079 14.293 18.3174C14.6835 17.9269 14.6835 17.2937 14.293 16.9032L10.1073 12.7175C9.71678 12.327 9.71678 11.6939 10.1073 11.3033L14.2893 7.12129C14.6799 6.73077 14.6799 6.0976 14.2893 5.70708Z" fill="#000000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 538 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.71069 18.2929C10.1012 18.6834 10.7344 18.6834 11.1249 18.2929L16.0123 13.4006C16.7927 12.6195 16.7924 11.3537 16.0117 10.5729L11.1213 5.68254C10.7308 5.29202 10.0976 5.29202 9.70708 5.68254C9.31655 6.07307 9.31655 6.70623 9.70708 7.09676L13.8927 11.2824C14.2833 11.6729 14.2833 12.3061 13.8927 12.6966L9.71069 16.8787C9.32016 17.2692 9.32016 17.9023 9.71069 18.2929Z" fill="#000000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 544 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="#FEFEFE" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2ZM16.06 13.79C15.91 13.94 15.72 14.01 15.53 14.01C15.34 14.01 15.15 13.94 15 13.79L12 10.79L9 13.79C8.71 14.08 8.23 14.08 7.94 13.79C7.65 13.5 7.65 13.02 7.94 12.73L11.47 9.2C11.76 8.91 12.24 8.91 12.53 9.2L16.06 12.73C16.35 13.03 16.35 13.5 16.06 13.79Z" fill="#000000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 523 B |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 3C4.55228 3 5 3.44772 5 4V5H7V4C7 3.44772 7.44772 3 8 3C8.55228 3 9 3.44772 9 4V5H11V4C11 3.44772 11.4477 3 12 3C12.5523 3 13 3.44772 13 4V5H15V4C15 3.44772 15.4477 3 16 3C16.5523 3 17 3.44772 17 4V5H19V4C19 3.44772 19.4477 3 20 3C20.5523 3 21 3.44772 21 4V6V18C21 19.6569 19.6569 21 18 21H6C4.34315 21 3 19.6569 3 18V6V4C3 3.44772 3.44772 3 4 3ZM19 7H16H12H8H5V18C5 18.5523 5.44772 19 6 19H18C18.5523 19 19 18.5523 19 18V7ZM13 10C13 10.5523 12.5523 11 12 11C11.4477 11 11 10.5523 11 10C11 9.44771 11.4477 9 12 9C12.5523 9 13 9.44771 13 10ZM16 11C16.5523 11 17 10.5523 17 10C17 9.44771 16.5523 9 16 9C15.4477 9 15 9.44771 15 10C15 10.5523 15.4477 11 16 11ZM9 13C9 13.5523 8.55228 14 8 14C7.44772 14 7 13.5523 7 13C7 12.4477 7.44772 12 8 12C8.55228 12 9 12.4477 9 13ZM12 14C12.5523 14 13 13.5523 13 13C13 12.4477 12.5523 12 12 12C11.4477 12 11 12.4477 11 13C11 13.5523 11.4477 14 12 14ZM17 13C17 13.5523 16.5523 14 16 14C15.4477 14 15 13.5523 15 13C15 12.4477 15.4477 12 16 12C16.5523 12 17 12.4477 17 13ZM8 17C8.55228 17 9 16.5523 9 16C9 15.4477 8.55228 15 8 15C7.44772 15 7 15.4477 7 16C7 16.5523 7.44772 17 8 17ZM13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15C12.5523 15 13 15.4477 13 16ZM16 17C16.5523 17 17 16.5523 17 16C17 15.4477 16.5523 15 16 15C15.4477 15 15 15.4477 15 16C15 16.5523 15.4477 17 16 17Z" fill="#000000"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" ?><svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2px;}</style></defs><title/><g id="cross"><line class="cls-1" x1="7" x2="25" y1="7" y2="25"/><line class="cls-1" x1="7" x2="25" y1="25" y2="7"/></g></svg>
|
||||
|
After Width: | Height: | Size: 334 B |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M1.293,11.293l4-4A1,1,0,1,1,6.707,8.707L3.414,12l3.293,3.293a1,1,0,1,1-1.414,1.414l-4-4A1,1,0,0,1,1.293,11.293Zm17.414-4a1,1,0,1,0-1.414,1.414L20.586,12l-3.293,3.293a1,1,0,1,0,1.414,1.414l4-4a1,1,0,0,0,0-1.414ZM13.039,4.726l-4,14a1,1,0,0,0,.686,1.236A1.053,1.053,0,0,0,10,20a1,1,0,0,0,.961-.726l4-14a1,1,0,1,0-1.922-.548Z"/></svg>
|
||||
|
After Width: | Height: | Size: 482 B |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Icons" x="-1024" y="0" width="1280" height="800" style="fill:none;"/><g id="Icons1" serif:id="Icons"><g id="Strike"></g><g id="H1"></g><g id="H2"></g><g id="H3"></g><g id="list-ul"></g><g id="hamburger-1"></g><g id="hamburger-2"></g><g id="list-ol"></g><g id="list-task"></g><g id="trash"></g><g id="vertical-menu"></g><g id="horizontal-menu"></g><g id="sidebar-2"></g><g id="Pen"></g><g id="Pen1" serif:id="Pen"><path d="M55.944,51.712l0,4.201l-33.652,-0.027l4.71,-4.174l28.942,0Zm-7.555,-43.712c1.649,0 2.505,0.128 4.752,2.011c2.294,1.921 2.707,3.419 2.803,5.087c0.102,1.795 -0.504,3.976 -2.188,5.681l-31.961,31.961c-0.52,0.475 -0.629,0.45 -0.977,0.553l-10.226,2.557c-1.472,0.299 -2.854,-1.049 -2.55,-2.55l2.557,-10.226c0.1,-0.334 0.133,-0.517 0.553,-0.976c10.696,-10.697 21.195,-21.594 32.09,-32.087c1.421,-1.335 3.497,-2.011 5.147,-2.011Zm-32.375,35.182l-1.477,1.477l-1.566,6.262l6.262,-1.566c0.493,-0.492 0.985,-0.983 1.479,-1.474l-4.698,-4.699Zm30.176,-20.573l-4.802,-4.801l-22.493,22.493l4.712,4.713c7.549,-7.448 15.196,-14.801 22.583,-22.405Zm2.826,-2.936c0.618,-0.648 1.234,-1.298 1.848,-1.951c1.673,-1.826 0.443,-5.454 -2.307,-5.578c-0.056,-0.002 -0.112,-0.002 -0.168,-0.002c-0.861,0.016 -1.699,0.372 -2.312,0.977l-1.807,1.808l4.746,4.746Z" style="fill-rule:nonzero;"/></g><g id="clock"></g><g id="external-link"></g><g id="hr"></g><g id="info"></g><g id="warning"></g><g id="plus-circle"></g><g id="minus-circle"></g><g id="vue"></g><g id="cog"></g><g id="logo"></g><g id="eye-slash"></g><g id="eye"></g><g id="toggle-off"></g><g id="shredder"></g><g id="spinner--loading--dots-" serif:id="spinner [loading, dots]"></g><g id="react"></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" version="1">
|
||||
<rect style="opacity:0.2" width="25" height="13" x="3" y="15" rx="1.25" ry="1.25"/>
|
||||
<path style="fill:#60924b" d="M 3,21.75 C 3,22.442 3.5575,23 4.25,23 H 26.75 C 27.442,23 28,22.442 28,21.75 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 H 4.25 C 3.5575,5 3,5.5575 3,6.25"/>
|
||||
<rect style="opacity:0.2" width="25" height="13" x="3" y="13" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e4e4e4" width="21" height="10" x="5" y="9" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#87b158" width="25" height="13" x="3" y="14" rx="1.25" ry="1.25"/>
|
||||
<path style="opacity:0.1;fill:#ffffff" d="M 4.25,5 C 3.557,5 3,5.5575 3,6.25 V 7.25 C 3,6.5575 3.557,6 4.25,6 H 12.75 C 13.443,6 14,6.5575 14,7.25 V 8 H 26.75 C 27.442,8 28,8.5575 28,9.25 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 918 B |
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" version="1">
|
||||
<rect style="opacity:0.2" width="25" height="13" x="3" y="15" rx="1.25" ry="1.25"/>
|
||||
<path style="fill:#727272" d="M 3,21.75 C 3,22.442 3.5575,23 4.25,23 H 26.75 C 27.442,23 28,22.442 28,21.75 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 H 4.25 C 3.5575,5 3,5.5575 3,6.25"/>
|
||||
<rect style="opacity:0.2" width="25" height="13" x="3" y="13" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e4e4e4" width="21" height="10" x="5" y="9" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#8e8e8e" width="25" height="13" x="3" y="14" rx="1.25" ry="1.25"/>
|
||||
<path style="opacity:0.1;fill:#ffffff" d="M 4.25,5 C 3.557,5 3,5.5575 3,6.25 V 7.25 C 3,6.5575 3.557,6 4.25,6 H 12.75 C 13.443,6 14,6.5575 14,7.25 V 8 H 26.75 C 27.442,8 28,8.5575 28,9.25 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 918 B |
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" version="1">
|
||||
<rect style="opacity:0.2" width="25" height="16" x="3" y="12" rx="1.25" ry="1.25"/>
|
||||
<path style="fill:#dd772f" d="M 3,21.75 C 3,22.442 3.5575,23 4.25,23 H 26.75 C 27.442,23 28,22.442 28,21.75 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 H 4.25 C 3.5575,5 3,5.5575 3,6.25"/>
|
||||
<rect style="opacity:0.2" width="25" height="16" x="3" y="10" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e4e4e4" width="21" height="10" x="5" y="9" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#ee923a" width="25" height="16" x="3" y="11" rx="1.25" ry="1.25"/>
|
||||
<path style="opacity:0.1;fill:#ffffff" d="M 4.25 5 C 3.5575 5 3 5.5575 3 6.25 L 3 7.25 C 3 6.5575 3.5575 6 4.25 6 L 12.75 6 C 13.443 6 14 6.5575 14 7.25 L 14 8 L 26.75 8 C 27.442 8 28 8.5575 28 9.25 L 28 8.25 C 28 7.5575 27.442 7 26.75 7 L 14 7 L 14 6.25 C 14 5.5575 13.443 5 12.75 5 L 4.25 5 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 946 B |
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" version="1">
|
||||
<rect style="opacity:0.2" width="25" height="16" x="3" y="12" rx="1.25" ry="1.25"/>
|
||||
<path style="fill:#bf4b4b" d="M 3,21.75 C 3,22.442 3.5575,23 4.25,23 H 26.75 C 27.442,23 28,22.442 28,21.75 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 H 4.25 C 3.5575,5 3,5.5575 3,6.25"/>
|
||||
<rect style="opacity:0.2" width="25" height="16" x="3" y="10" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e4e4e4" width="21" height="10" x="5" y="9" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e25252" width="25" height="16" x="3" y="11" rx="1.25" ry="1.25"/>
|
||||
<path style="opacity:0.1;fill:#ffffff" d="M 4.25 5 C 3.5575 5 3 5.5575 3 6.25 L 3 7.25 C 3 6.5575 3.5575 6 4.25 6 L 12.75 6 C 13.443 6 14 6.5575 14 7.25 L 14 8 L 26.75 8 C 27.442 8 28 8.5575 28 9.25 L 28 8.25 C 28 7.5575 27.442 7 26.75 7 L 14 7 L 14 6.25 C 14 5.5575 13.443 5 12.75 5 L 4.25 5 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 946 B |
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" version="1">
|
||||
<rect style="opacity:0.2" width="25" height="16" x="3" y="12" rx="1.25" ry="1.25"/>
|
||||
<path style="fill:#b58f1b" d="M 3,21.75 C 3,22.442 3.5575,23 4.25,23 H 26.75 C 27.442,23 28,22.442 28,21.75 V 8.25 C 28,7.5575 27.442,7 26.75,7 H 14 V 6.25 C 14,5.5575 13.443,5 12.75,5 H 4.25 C 3.5575,5 3,5.5575 3,6.25"/>
|
||||
<rect style="opacity:0.2" width="25" height="16" x="3" y="10" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e4e4e4" width="21" height="10" x="5" y="9" rx="1.25" ry="1.25"/>
|
||||
<rect style="fill:#e2b322" width="25" height="16" x="3" y="11" rx="1.25" ry="1.25"/>
|
||||
<path style="opacity:0.1;fill:#ffffff" d="M 4.25 5 C 3.5575 5 3 5.5575 3 6.25 L 3 7.25 C 3 6.5575 3.5575 6 4.25 6 L 12.75 6 C 13.443 6 14 6.5575 14 7.25 L 14 8 L 26.75 8 C 27.442 8 28 8.5575 28 9.25 L 28 8.25 C 28 7.5575 27.442 7 26.75 7 L 14 7 L 14 6.25 C 14 5.5575 13.443 5 12.75 5 L 4.25 5 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 946 B |
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" ?><svg data-name="Livello 1" id="Livello_1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><title/>
|
||||
<path d="M64,39A25,25,0,1,0,89,64,25,25,0,0,0,64,39Zm0,44A19,19,0,1,1,83,64,19,19,0,0,1,64,83Z"/>
|
||||
<path d="M121,48h-8.93a1,1,0,0,1-.94-.68,49.9,49.9,0,0,0-2-4.85,1,1,0,0,1,.18-1.15L115.62,35a7,7,0,0,0,0-9.9L102.89,12.38a7,7,0,0,0-9.9,0l-6.31,6.31a1,1,0,0,1-1.15.18,49.76,49.76,0,0,0-4.85-2,1,1,0,0,1-.68-.94V7a7,7,0,0,0-7-7H55a7,7,0,0,0-7,7v8.93a1,1,0,0,1-.68.94,49.9,49.9,0,0,0-4.85,2,1,1,0,0,1-1.15-.18L35,12.38a7,7,0,0,0-9.9,0L12.38,25.11a7,7,0,0,0,0,9.9l6.31,6.31a1,1,0,0,1,.18,1.15,49.76,49.76,0,0,0-2,4.85,1,1,0,0,1-.94.68H7a7,7,0,0,0-7,7V73a7,7,0,0,0,7,7h8.93a1,1,0,0,1,.94.68,49.9,49.9,0,0,0,2,4.85,1,1,0,0,1-.18,1.15L12.38,93a7,7,0,0,0,0,9.9l12.73,12.73a7,7,0,0,0,9.9,0l6.31-6.31a1,1,0,0,1,1.15-.18,49.76,49.76,0,0,0,4.85,2,1,1,0,0,1,.68.94V121a7,7,0,0,0,7,7H73a7,7,0,0,0,7-7v-8.93a1,1,0,0,1,.68-.94,49.9,49.9,0,0,0,4.85-2,1,1,0,0,1,1.15.18L93,115.62a7,7,0,0,0,9.9,0l12.73-12.73a7,7,0,0,0,0-9.9l-6.31-6.31a1,1,0,0,1-.18-1.15,49.76,49.76,0,0,0,2-4.85,1,1,0,0,1,.94-.68H121a7,7,0,0,0,7-7V55A7,7,0,0,0,121,48Zm1,25a1,1,0,0,1-1,1h-8.93a7,7,0,0,0-6.6,4.69,43.9,43.9,0,0,1-1.76,4.26,7,7,0,0,0,1.35,8l6.31,6.31a1,1,0,0,1,0,1.41L98.65,111.38a1,1,0,0,1-1.41,0l-6.31-6.31a7,7,0,0,0-8-1.35,43.88,43.88,0,0,1-4.27,1.76,7,7,0,0,0-4.68,6.6V121a1,1,0,0,1-1,1H55a1,1,0,0,1-1-1v-8.93a7,7,0,0,0-4.69-6.6,43.9,43.9,0,0,1-4.26-1.76,7,7,0,0,0-8,1.35l-6.31,6.31a1,1,0,0,1-1.41,0L16.62,98.65a1,1,0,0,1,0-1.41l6.31-6.31a7,7,0,0,0,1.35-8,43.88,43.88,0,0,1-1.76-4.27A7,7,0,0,0,15.93,74H7a1,1,0,0,1-1-1V55a1,1,0,0,1,1-1h8.93a7,7,0,0,0,6.6-4.69,43.9,43.9,0,0,1,1.76-4.26,7,7,0,0,0-1.35-8l-6.31-6.31a1,1,0,0,1,0-1.41L29.35,16.62a1,1,0,0,1,1.41,0l6.31,6.31a7,7,0,0,0,8,1.35,43.88,43.88,0,0,1,4.27-1.76A7,7,0,0,0,54,15.93V7a1,1,0,0,1,1-1H73a1,1,0,0,1,1,1v8.93a7,7,0,0,0,4.69,6.6,43.9,43.9,0,0,1,4.26,1.76,7,7,0,0,0,8-1.35l6.31-6.31a1,1,0,0,1,1.41,0l12.73,12.73a1,1,0,0,1,0,1.41l-6.31,6.31a7,7,0,0,0-1.35,8,43.88,43.88,0,0,1,1.76,4.27,7,7,0,0,0,6.6,4.68H121a1,1,0,0,1,1,1Z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 512 512">
|
||||
<path d="M377.9 105.9L500.7 228.7c7.2 7.2 11.3 17.1 11.3 27.3s-4.1 20.1-11.3 27.3L377.9 406.1c-6.4 6.4-15 9.9-24 9.9c-18.7 0-33.9-15.2-33.9-33.9l0-62.1-128 0c-17.7 0-32-14.3-32-32l0-64c0-17.7 14.3-32 32-32l128 0 0-62.1c0-18.7 15.2-33.9 33.9-33.9c9 0 17.6 3.6 24 9.9zM160 96L96 96c-17.7 0-32 14.3-32 32l0 256c0 17.7 14.3 32 32 32l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-64 0c-53 0-96-43-96-96L0 128C0 75 43 32 96 32l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 502 B |
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
␍<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 52 52" xmlns="http://www.w3.org/2000/svg">
|
||||
␍<g>
|
||||
␍<path d="m28.6 11.4h5.1a1.11 1.11 0 0 0 1.1-1.1 1.32 1.32 0 0 0 -.3-.8l-7.2-7.1a.89.89 0 0 0 -.7-.3 1.11 1.11 0 0 0 -1.1 1.1v5.1a3.12 3.12 0 0 0 3.1 3.1z"/>
|
||||
␍<path d="m49.83 32.45a1.43 1.43 0 0 0 -1.39-1.45h-12a1.43 1.43 0 0 0 -1.44 1.44v1.44a1.43 1.43 0 0 0 1.4 1.44h6.14l-11 11a1.42 1.42 0 0 0 0 2l1 1a1.54 1.54 0 0 0 1.09.45 1.32 1.32 0 0 0 .94-.38l11-11v6a1.43 1.43 0 0 0 1.43 1.44h1.53a1.43 1.43 0 0 0 1.47-1.4z"/>
|
||||
␍<path d="m18.35 20.68h-1.46v4.93h1.46a1.56 1.56 0 0 0 1.56-1.1 3.93 3.93 0 0 0 .24-1.44 3.61 3.61 0 0 0 -.36-1.77 1.53 1.53 0 0 0 -1.44-.62z"/>
|
||||
␍<path d="m11.29 20.93a1.27 1.27 0 0 0 -.84-.25h-1.45v2.23h1.46a1.18 1.18 0 0 0 .84-.28 1.09 1.09 0 0 0 .3-.86 1 1 0 0 0 -.33-.84z"/>
|
||||
␍<path d="m33.24 16h-7.84a4.67 4.67 0 0 1 -4.7-4.6v-7.8a1.42 1.42 0 0 0 -1.34-1.5h-12.56a4.67 4.67 0 0 0 -4.7 4.6v29.4a4.6 4.6 0 0 0 4.62 4.6h17.88v-.1a15.92 15.92 0 0 1 10.2-14.9v-8.1a1.58 1.58 0 0 0 -1.56-1.6zm-20.75 7.65a2.93 2.93 0 0 1 -1.89.56h-1.6v2.71h-1.51v-7.55h3.24a2.64 2.64 0 0 1 1.76.63 2.3 2.3 0 0 1 .66 1.8 2.35 2.35 0 0 1 -.66 1.85zm8.66 1.9a2.73 2.73 0 0 1 -2.53 1.45h-3.26v-7.63h3.26a3.85 3.85 0 0 1 1.17.17 2.49 2.49 0 0 1 1.28.95 3.43 3.43 0 0 1 .54 1.22 5.6 5.6 0 0 1 .14 1.29 5 5 0 0 1 -.6 2.55zm7.92-4.84h-3.81v1.74h3.34v1.31h-3.34v3.16h-1.57v-7.54h5.38z"/>
|
||||
␍</g>
|
||||
␍</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 64 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Icons" x="-896" y="-128" width="1280" height="800" style="fill:none;"/><g id="Icons1" serif:id="Icons"><g id="Strike"></g><g id="H1"></g><g id="H2"></g><g id="H3"></g><g id="list-ul"></g><g id="hamburger-1"></g><g id="hamburger-2"></g><g id="list-ol"></g><g id="list-task"></g><g id="trash"></g><g id="vertical-menu"></g><g id="horizontal-menu"></g><g id="sidebar-2"></g><g id="Pen"></g><g id="Pen1" serif:id="Pen"></g><g id="clock"></g><g id="external-link"></g><g id="hr"></g><g id="info"></g><g id="warning"></g><g id="plus-circle"></g><g id="minus-circle"></g><g><path id="caret-down" d="M45.274,29.772c-1.094,-8.15 -8.075,-14.435 -16.525,-14.435c-9.203,0 -16.674,7.471 -16.674,16.674c0,9.203 7.471,16.675 16.674,16.675c4.423,0 8.664,-1.757 11.791,-4.884l2.862,2.863c-3.886,3.886 -9.157,6.069 -14.653,6.069c-11.437,0 -20.723,-9.285 -20.723,-20.723c0,-11.437 9.286,-20.723 20.723,-20.723c10.623,0 19.379,7.994 20.582,18.294l3.551,-3.551l3.118,3.117l-8.792,8.792l-8.796,-8.796l3.118,-3.117l3.744,3.745Z" style="fill-rule:nonzero;"/></g><g id="vue"></g><g id="cog"></g><g id="logo"></g><g id="eye-slash"></g><g id="eye"></g><g id="toggle-off"></g><g id="shredder"></g><g id="spinner--loading--dots-" serif:id="spinner [loading, dots]"></g><g id="react"></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M1.75 4.5a.25.25 0 00-.25.25v14.5c0 .138.112.25.25.25h20.5a.25.25 0 00.25-.25V4.75a.25.25 0 00-.25-.25H1.75zM0 4.75C0 3.784.784 3 1.75 3h20.5c.966 0 1.75.784 1.75 1.75v14.5A1.75 1.75 0 0122.25 21H1.75A1.75 1.75 0 010 19.25V4.75z"/>
|
||||
<path d="M9 15.584V8.416a.5.5 0 01.77-.42l5.576 3.583a.5.5 0 010 .842L9.77 16.005a.5.5 0 01-.77-.42z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 515 B |
@@ -0,0 +1,9 @@
|
||||
<footer id="footer">
|
||||
<div class="legal-links">
|
||||
<a href="https://nak-reinickendorf.de/impressum.php">Impressum</a>
|
||||
<a href="#" onclick="openContactModal(); return false;">Admin kontaktieren</a>
|
||||
<a href="https://nak-reinickendorf.de/datenschutz.php">Datenschutz</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/snippets/contact_modal.php'; ?>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php /* Name: header.php
|
||||
Beschreibung: Ausgabe des Seitenkopfes inkl. Intranet-Menü
|
||||
- Profil-Leiste */
|
||||
?>
|
||||
<header>
|
||||
<div class="header_menue unselectable" id="header_menue">
|
||||
|
||||
<a class="nak-logo-link" href="<?php echo $g_httpHomePath; ?>">
|
||||
<img src="/intranet_repo/projects/_central/img/nak-logo.svg" alt="NAK" class="nak-logo-icon">
|
||||
<div class="nak-logo-text">
|
||||
<span class="nak-name">Neuapostolische Kirche</span>
|
||||
<span class="nak-gemeinde">Berlin-Reinickendorf</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="header_profile" id="header_profile">
|
||||
|
||||
<?php // Profilbild
|
||||
// Generiere den Dateinamen basierend auf Benutzer-ID und Datum/Uhrzeit
|
||||
$profileImg = glob($g_profilePicturePath."{$_SESSION['user_id']}-*.jpg");
|
||||
|
||||
// Überprüfe, ob eine passende Datei existiert
|
||||
if (!empty($profileImg)) {
|
||||
// Sortiere die Dateien nach Datum/Uhrzeit und nimm die neueste
|
||||
usort($profileImg, function($a, $b) {
|
||||
return filemtime($b) - filemtime($a);
|
||||
});
|
||||
$latestProfileImg = $profileImg[0];
|
||||
|
||||
// Entferne den absoluten Pfad
|
||||
$headerProfileImg = str_replace($_SERVER['DOCUMENT_ROOT'], '', $latestProfileImg);
|
||||
} else {
|
||||
// Standardbild, wenn keine passende Datei gefunden wurde
|
||||
$headerProfileImg = "/intranet_repo/general_files/profile_pictures/default.jpg";
|
||||
}
|
||||
|
||||
// Bild anzeigen
|
||||
echo "<img src='$headerProfileImg' alt='Profil' id='header_profile_img' onclick='openCloseHeaderProfile();'>";
|
||||
?>
|
||||
|
||||
<div class="header_profile_bar" onclick="window.location.href='<?php echo $g_httpLogoutPath; ?>';">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16"><path d="M17 7l-1.41 1.41L18.17 11H8v2h10.17l-2.58 2.58L17 17l5-5zM4 5h8V3H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8v-2H4V5z"/></svg>
|
||||
<span>Abmelden</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php /* Name: html_head.php
|
||||
Beschreibung: Zentraler HTML Head für das Intranet und Kalli
|
||||
|
||||
Anforderung: Umschliessendes Tag für diese Datei erforderlich: <head>...</head> */
|
||||
|
||||
|
||||
?>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Language" content="de">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="/intranet_repo/projects/_central/img/nak-logo.svg">
|
||||
<link rel="shortcut icon" href="/intranet_repo/projects/_central/img/favicon.ico">
|
||||
<link rel="stylesheet" href="/intranet_repo/projects/_central/layouts/nak-design.css">
|
||||
|
||||
<script src="/intranet_repo/projects/_central/scripts/intranet.js"></script>
|
||||
|
||||
<title>NAK Berlin-Reinickendorf</title>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php /* Name: button_edit.php
|
||||
Beschreibung: Button-Ausgabe für die Umschaltung auf den Bearbeitungsmodus
|
||||
|
||||
GET-Parameter: action=edit
|
||||
id=[$edit_id] */
|
||||
?>
|
||||
|
||||
<div class="right">
|
||||
|
||||
<?php
|
||||
if (isset($_GET['action']) && $_GET['action'] == 'edit') {
|
||||
|
||||
display_button('edit','Bearbeiten','right');
|
||||
} else {
|
||||
|
||||
if (isset($edit_id)) {
|
||||
echo "<a href='".$g_httpCurrentCleanUrl."?action=edit&id=$edit_id' style='display:table-cell;'>";
|
||||
} else {
|
||||
echo "<a href='".$g_httpCurrentCleanUrl."?action=edit' style='display:table-cell;'>";
|
||||
}
|
||||
display_button('edit','Bearbeiten','right');
|
||||
echo "</a>";
|
||||
}
|
||||
?>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php /* Name: contact_modal.php
|
||||
Beschreibung: Globales Kontaktformular-Modal
|
||||
- Wird überall eingebunden wo technik@-Link war
|
||||
- Sendet per AJAX an process_contact.php */
|
||||
?>
|
||||
|
||||
<!-- Kontaktformular Modal -->
|
||||
<div class="standard_overlay" id="contactModal" onclick="closeContactModalOnBackdrop(event)">
|
||||
<div style="position:relative;width:min(520px,calc(100vw - 24px));max-height:min(700px,calc(100vh - 24px));overflow:auto;background:#FFF;border-radius:0;box-shadow:0 24px 70px rgba(0,0,0,0.36);">
|
||||
<button type="button" onclick="closeContactModal()" style="position:absolute;top:14px;right:14px;width:34px;height:34px;border-radius:0;border:1px solid rgba(255,255,255,0.25);background:rgba(255,255,255,0.16);color:#FFF;font-size:1.35em;cursor:pointer;z-index:1;">×</button>
|
||||
|
||||
<div style="padding:24px;color:#FFF;background:radial-gradient(circle at 10% 0%,rgba(255,255,255,0.24),transparent 32%),linear-gradient(135deg,var(--theme-color),var(--theme-hover));border-radius:0;">
|
||||
<div style="font-size:1.3em;font-weight:850;">Admin kontaktieren</div>
|
||||
<div style="margin-top:6px;color:rgba(255,255,255,0.8);font-weight:600;">Ihr Anliegen wird an den Administrator weitergeleitet.</div>
|
||||
</div>
|
||||
|
||||
<div style="padding:22px 24px 24px 24px;">
|
||||
<form id="contactForm" onsubmit="submitContactForm(event)">
|
||||
<?php
|
||||
$isLoggedIn = isset($user) && !empty($user['first_name']) && !empty($user['mail']);
|
||||
$prefillName = $isLoggedIn ? htmlspecialchars($user['first_name'] . ' ' . $user['last_name']) : '';
|
||||
$prefillMail = $isLoggedIn ? htmlspecialchars($user['mail']) : '';
|
||||
$readonlyAttr = $isLoggedIn ? 'readonly' : '';
|
||||
$readonlyStyle = $isLoggedIn ? 'cursor:not-allowed;opacity:0.7;' : '';
|
||||
?>
|
||||
|
||||
<label style="display:block;margin-bottom:4px;font-weight:750;font-size:0.88em;color:hsl(210,18%,36%);text-transform:uppercase;letter-spacing:0.04em;">Name</label>
|
||||
<input type="text" name="contact_name" id="contact_name" required <?= $readonlyAttr ?>
|
||||
value="<?= $prefillName ?>"
|
||||
style="width:100%;padding:12px 14px;border:1px solid hsl(210,18%,84%);border-radius:0;background:hsl(210,12%,98%);font-size:1em;font-weight:650;outline:none;margin-bottom:12px;box-sizing:border-box;<?= $readonlyStyle ?>">
|
||||
|
||||
<label style="display:block;margin-bottom:4px;font-weight:750;font-size:0.88em;color:hsl(210,18%,36%);text-transform:uppercase;letter-spacing:0.04em;">E-Mail</label>
|
||||
<input type="email" name="contact_email" id="contact_email" required <?= $readonlyAttr ?>
|
||||
value="<?= $prefillMail ?>"
|
||||
style="width:100%;padding:12px 14px;border:1px solid hsl(210,18%,84%);border-radius:0;background:hsl(210,12%,98%);font-size:1em;font-weight:650;outline:none;margin-bottom:12px;box-sizing:border-box;<?= $readonlyStyle ?>">
|
||||
|
||||
<?php if ($isLoggedIn): ?>
|
||||
<div style="margin:-8px 0 12px 0;font-size:0.82em;color:hsl(210,14%,50%);font-weight:600;">Ihre Kontaktdaten werden automatisch aus Ihrem Profil übernommen.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<label style="display:block;margin-bottom:4px;font-weight:750;font-size:0.88em;color:hsl(210,18%,36%);text-transform:uppercase;letter-spacing:0.04em;">Betreff</label>
|
||||
<input type="text" name="contact_subject" id="contact_subject" required
|
||||
style="width:100%;padding:12px 14px;border:1px solid hsl(210,18%,84%);border-radius:0;background:hsl(210,12%,98%);font-size:1em;font-weight:650;outline:none;margin-bottom:12px;box-sizing:border-box;">
|
||||
|
||||
<label style="display:block;margin-bottom:4px;font-weight:750;font-size:0.88em;color:hsl(210,18%,36%);text-transform:uppercase;letter-spacing:0.04em;">Nachricht</label>
|
||||
<textarea name="contact_message" id="contact_message" rows="5" required
|
||||
style="width:100%;padding:12px 14px;border:1px solid hsl(210,18%,84%);border-radius:0;background:hsl(210,12%,98%);font-size:1em;font-weight:650;outline:none;margin-bottom:16px;resize:vertical;box-sizing:border-box;font-family:inherit;"></textarea>
|
||||
|
||||
<div style="display:flex;justify-content:flex-end;gap:8px;">
|
||||
<button type="button" onclick="closeContactModal()" style="padding:8px 16px;border:1px solid hsl(210,18%,84%);border-radius:0;background:#FFF;font-weight:850;font-size:0.86em;cursor:pointer;">Abbrechen</button>
|
||||
<button type="submit" id="contactSubmitBtn" style="padding:8px 16px;border:1px solid var(--theme-color);border-radius:0;background:linear-gradient(135deg,var(--theme-color),var(--theme-hover));color:#FFF;font-weight:850;font-size:0.86em;cursor:pointer;">Nachricht senden</button>
|
||||
</div>
|
||||
</form>
|
||||
<div id="contactFormResult" style="display:none;margin-top:12px;padding:10px 14px;border-radius:0;font-weight:700;text-align:center;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openContactModal() {
|
||||
document.getElementById('contactModal').style.display = 'flex';
|
||||
}
|
||||
function closeContactModal() {
|
||||
document.getElementById('contactModal').style.display = 'none';
|
||||
document.getElementById('contactFormResult').style.display = 'none';
|
||||
document.getElementById('contactSubmitBtn').disabled = false;
|
||||
document.getElementById('contactSubmitBtn').textContent = 'Nachricht senden';
|
||||
}
|
||||
function closeContactModalOnBackdrop(event) {
|
||||
if (event.target.id === 'contactModal') closeContactModal();
|
||||
}
|
||||
function submitContactForm(event) {
|
||||
event.preventDefault();
|
||||
const form = document.getElementById('contactForm');
|
||||
const resultDiv = document.getElementById('contactFormResult');
|
||||
const submitBtn = document.getElementById('contactSubmitBtn');
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = 'Wird gesendet...';
|
||||
|
||||
const formData = new FormData(form);
|
||||
|
||||
fetch('/intranet_repo/projects/adminpanel/process_contact.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resultDiv.style.display = 'block';
|
||||
if (data.success) {
|
||||
resultDiv.style.background = 'hsl(145, 50%, 93%)';
|
||||
resultDiv.style.color = 'hsl(145, 50%, 28%)';
|
||||
resultDiv.textContent = 'Nachricht erfolgreich gesendet!';
|
||||
form.reset();
|
||||
setTimeout(() => closeContactModal(), 2000);
|
||||
} else {
|
||||
resultDiv.style.background = 'hsl(0, 78%, 95%)';
|
||||
resultDiv.style.color = 'hsl(0, 78%, 40%)';
|
||||
resultDiv.textContent = data.error || 'Ein Fehler ist aufgetreten.';
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = 'Nachricht senden';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
resultDiv.style.display = 'block';
|
||||
resultDiv.style.background = 'hsl(0, 78%, 95%)';
|
||||
resultDiv.style.color = 'hsl(0, 78%, 40%)';
|
||||
resultDiv.textContent = 'Verbindungsfehler. Bitte erneut versuchen.';
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.textContent = 'Nachricht senden';
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Escape' && document.getElementById('contactModal').style.display === 'flex') {
|
||||
closeContactModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
Name: countdown.php
|
||||
Beschreibung: Reload der aktuellen Seite mit Countdown
|
||||
*/
|
||||
?>
|
||||
|
||||
<div class="countdown"><span id="countdown">120</span></div>
|
||||
|
||||
<script>
|
||||
var countdown = document.getElementById("countdown").textContent;
|
||||
|
||||
let pauseCountdown = false; //Von außen kann der Countdown angehalten werden: pauseCountdown = true
|
||||
|
||||
var countdownTimer = setInterval(function() {
|
||||
|
||||
if (!pauseCountdown) {
|
||||
|
||||
countdown--;
|
||||
document.getElementById('countdown').textContent = countdown;
|
||||
|
||||
if ((countdown <= 0)) {
|
||||
|
||||
clearInterval(countdownTimer);
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
}, 1000);
|
||||
</script>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php /* Name: overlay_addNewUser.php
|
||||
Beschreibung: Neuen Nutzer anlegen in einem Overlay
|
||||
- wird in admin.php aufgerufen */
|
||||
|
||||
// Neuen Nutzer anlegen im Overlay (Formular) ?>
|
||||
<div class="standard_overlay" id="addNewUser">
|
||||
<div class="bg_blur"></div>
|
||||
<form method="post" action="">
|
||||
<div class="eventbox_mini center">
|
||||
<div class="exit" onclick="openCloseOverlay('addNewUser')">
|
||||
<?php display_button('cancel','','center'); ?>
|
||||
</div>
|
||||
<h3 style="margin-top:15px;margin-left:5px;margin-bottom:15px">Neuen Nutzer anlegen</h3>
|
||||
<div class="item">
|
||||
<input class="field" placeholder="E-Mailadresse" type="text" name="newMail"required>
|
||||
<input class="button" type="submit" name="addRecord" value="Hinzufügen">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php /* Name: overlay_message.php
|
||||
Beschreibung: Ausgabe einer Message als Toast-Notification
|
||||
|
||||
Anforderung: Ausgabe möglichst zum <body>-Beginn. */
|
||||
|
||||
|
||||
// Mapping aller Intranet-Messageboxen mit Typ und Ausgabetext
|
||||
function getMessageInfo($message) {
|
||||
return match ($message) {
|
||||
1 => ['type' => 'success', 'text' => "Passwort zurückgesetzt."],
|
||||
2 => ['type' => 'success', 'text' => "Nutzer entfernt."],
|
||||
3 => ['type' => 'success', 'text' => "Nutzer angelegt."],
|
||||
4 => ['type' => 'error', 'text' => "Nutzer existiert bereits."],
|
||||
5 => ['type' => 'success', 'text' => "Speicherung erfolgt."],
|
||||
6 => ['type' => 'success', 'text' => "Einladungsmail gesendet."],
|
||||
7 => ['type' => 'error', 'text' => "Bitte Name und E-Mail ausfüllen."],
|
||||
8 => ['type' => 'success', 'text' => "Brandschutzschulung abgeschlossen. Vielen Dank für deine Teilnahme!"],
|
||||
|
||||
default => ['type' => 'error', 'text' => "Unbekannter Fehler."],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Laden der Message
|
||||
if (isset($_GET["message"])) {
|
||||
$message = intval($_GET["message"]);
|
||||
$messageInfo = getMessageInfo($message);
|
||||
$toastType = $messageInfo['type'];
|
||||
$toastText = $messageInfo['text'];
|
||||
|
||||
?>
|
||||
<div class="nak-toast nak-toast--<?= $toastType ?>" id="nakToast">
|
||||
<div class="nak-toast__icon">
|
||||
<?php if ($toastType === 'success'): ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
<?php else: ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<span class="nak-toast__text"><?= htmlspecialchars($toastText) ?></span>
|
||||
<button class="nak-toast__close" onclick="dismissNakToast()" aria-label="Schließen">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var toast = document.getElementById('nakToast');
|
||||
if (!toast) return;
|
||||
// Slide in
|
||||
requestAnimationFrame(function() {
|
||||
toast.classList.add('nak-toast--visible');
|
||||
});
|
||||
// Auto-dismiss after 4s
|
||||
var timer = setTimeout(function() { dismissNakToast(); }, 4000);
|
||||
toast._timer = timer;
|
||||
// Clean URL
|
||||
if (window.history && window.history.replaceState) {
|
||||
var url = new URL(window.location);
|
||||
url.searchParams.delete('message');
|
||||
window.history.replaceState({}, '', url);
|
||||
}
|
||||
})();
|
||||
function dismissNakToast() {
|
||||
var toast = document.getElementById('nakToast');
|
||||
if (!toast || toast.classList.contains('nak-toast--hiding')) return;
|
||||
clearTimeout(toast._timer);
|
||||
toast.classList.add('nak-toast--hiding');
|
||||
toast.classList.remove('nak-toast--visible');
|
||||
setTimeout(function() { toast.remove(); }, 350);
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php } ?>
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php /* Name: overlay_profile.php
|
||||
Beschreibung: Profil eines ausgewählten Nutzers im Overlay */
|
||||
?>
|
||||
|
||||
<?php
|
||||
if (isset($_SESSION["profile_id"])) {
|
||||
$pdo = require($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
|
||||
$sql = "SELECT * FROM user_general_information
|
||||
WHERE user_id = {$_SESSION["profile_id"]}";
|
||||
$result = $pdo->query($sql);
|
||||
$partner = $result->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (isset($partner["mail"])) {
|
||||
$sql_groups = "SELECT * FROM user_permissions WHERE user_id = ?";
|
||||
$stmt = $pdo->prepare($sql_groups);
|
||||
$stmt->execute([$_SESSION["profile_id"]]);
|
||||
$groups = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
}
|
||||
else {
|
||||
header("Location:{$g_httpLoginPath}");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Profile image
|
||||
$profileImg = glob($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/profile_pictures/{$_SESSION["profile_id"]}-*.jpg");
|
||||
if (!empty($profileImg)) {
|
||||
usort($profileImg, function($a, $b) { return filemtime($b) - filemtime($a); });
|
||||
$profileImgUrl = str_replace($_SERVER['DOCUMENT_ROOT'], '', $profileImg[0]);
|
||||
} else {
|
||||
$profileImgUrl = "/intranet_repo/general_files/profile_pictures/default.jpg";
|
||||
}
|
||||
|
||||
$fullName = trim(($partner["first_name"] ?? '') . ' ' . ($partner["last_name"] ?? ''));
|
||||
$isRegistered = !empty($partner["first_name"]);
|
||||
?>
|
||||
|
||||
<div class="profile-modal-card">
|
||||
<button type="button" class="exit" aria-label="Schließen" onclick="openCloseProfile(0, '<?= $profile_container_name ?>', '<?= $profile_overlay_id ?>');">×</button>
|
||||
|
||||
<div class="profile-modal-hero">
|
||||
<img class="profile-modal-img" src="<?= htmlspecialchars($profileImgUrl) ?>" alt="Profilbild">
|
||||
<div>
|
||||
<?php if ($isRegistered): ?>
|
||||
<div class="profile-modal-title"><?= htmlspecialchars($fullName) ?></div>
|
||||
<?php else: ?>
|
||||
<div class="profile-modal-title" style="color:rgba(255,255,255,0.7);">Nicht registriert</div>
|
||||
<?php endif; ?>
|
||||
<div class="profile-modal-subtitle">
|
||||
<span><?= htmlspecialchars($partner["mail"]) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="profile-modal-body">
|
||||
<?php if ($partner["phone"] != null): ?>
|
||||
<div class="profile-modal-field">
|
||||
<div class="profile-modal-field-label">Telefon</div>
|
||||
<div class="profile-modal-field-value">
|
||||
<a href="tel:0<?= htmlspecialchars($partner["phone"]) ?>">0<?= htmlspecialchars($partner["phone"]) ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($groups)): ?>
|
||||
<div class="profile-modal-field">
|
||||
<div class="profile-modal-field-label">Gruppen</div>
|
||||
<div class="profile-modal-chips">
|
||||
<?php
|
||||
foreach ($groups as $key => $value) {
|
||||
if ($value == 1) {
|
||||
echo '<span class="profile-modal-chip">' . htmlspecialchars($key) . '</span>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,199 @@
|
||||
////==========================================//
|
||||
//// GLOBALER BEREICH //
|
||||
////////////////////////////////////////////////
|
||||
//// Globale Konstanten
|
||||
const url = new URL(window.location.href);
|
||||
const basisUrl = url.origin + url.pathname;
|
||||
////
|
||||
////////////////////////////////////////////////
|
||||
////==========================================//
|
||||
|
||||
|
||||
|
||||
////==========================================//
|
||||
//// FUNKTIONEN und LISTENER //
|
||||
////////////////////////////////////////////////
|
||||
////
|
||||
|
||||
// Position der Elemente – min-height wird jetzt vollständig per CSS gelöst (nak-design.css)
|
||||
// Die alte JS-Berechnung wurde entfernt, da sie nach dem Laden die Höhe reduzierte.
|
||||
|
||||
|
||||
// JavaScript zum Erkennen der Scroll-Richtung und zum Umschalten der Klasse
|
||||
// Funktioniert sowohl bei Body-Scroll als auch bei internem Container-Scroll (z.B. eventbox_table)
|
||||
var lastScrollTop = 0;
|
||||
var lastContainerScrollTop = 0;
|
||||
|
||||
function handleHeaderScroll(scrollTop, lastScroll) {
|
||||
const elemHeaderMenue = document.getElementById('header_menue');
|
||||
const elemHeaderTitle = document.getElementById('header_title');
|
||||
|
||||
// Dynamische Höhe aus CSS-Variable lesen
|
||||
const headerHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 64;
|
||||
|
||||
// Kein Einfahren, wenn der Content auf die Seite passt (kein Scrollen nötig)
|
||||
if (document.documentElement.scrollHeight <= window.innerHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Am unteren Ende der Seite: Header wieder einblenden
|
||||
const atBottom = (window.innerHeight + window.scrollY) >= (document.documentElement.scrollHeight - 5);
|
||||
|
||||
if (scrollTop > lastScroll && !atBottom) {
|
||||
// Menü raus bei Scroll nach unten
|
||||
if (elemHeaderMenue) {
|
||||
elemHeaderMenue.style.top = `-${headerHeight}px`;
|
||||
elemHeaderMenue.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
if (elemHeaderTitle) {
|
||||
elemHeaderTitle.style.top = "0";
|
||||
elemHeaderTitle.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
} else {
|
||||
// Menü wieder rein bei Scroll nach oben
|
||||
if (elemHeaderMenue) {
|
||||
elemHeaderMenue.style.top = "0";
|
||||
elemHeaderMenue.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
if (elemHeaderTitle) {
|
||||
elemHeaderTitle.style.top = `${headerHeight}px`;
|
||||
elemHeaderTitle.style.transition = "top 0.3s ease-in-out";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Body/Document Scroll
|
||||
document.addEventListener("scroll", function() {
|
||||
var st = window.scrollY || document.documentElement.scrollTop;
|
||||
handleHeaderScroll(st, lastScrollTop);
|
||||
lastScrollTop = st <= 0 ? 0 : st;
|
||||
}, false);
|
||||
|
||||
// Auch bei internem Container-Scroll (eventbox_table, display_within_dev)
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const scrollContainers = document.querySelectorAll('.eventbox_table, form.display_within_dev');
|
||||
scrollContainers.forEach(function(container) {
|
||||
var lastCST = 0;
|
||||
container.addEventListener("scroll", function() {
|
||||
var st = container.scrollTop;
|
||||
handleHeaderScroll(st, lastCST);
|
||||
lastCST = st <= 0 ? 0 : st;
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function openCloseHeaderProfile() {
|
||||
if (window.innerWidth >= 769) {
|
||||
// Desktop: click on profile image goes to profile page
|
||||
window.location.href = '/intranet_repo/projects/intranet/profile.php';
|
||||
} else {
|
||||
// Mobile: toggle expand/collapse
|
||||
const hpElem = document.getElementById('header_profile');
|
||||
hpElem.classList.toggle('header_profile_slideLeft');
|
||||
}
|
||||
}
|
||||
|
||||
function openCloseOverlay(id) {
|
||||
//Overlay ein-/ausblenden - beim Ausblenden zurück auf eigene Seite
|
||||
const elem = document.getElementById(id);
|
||||
|
||||
if (elem.style.display === "flex") {
|
||||
elem.style.display = "none";
|
||||
} else {
|
||||
elem.style.display = "flex";
|
||||
}
|
||||
}
|
||||
|
||||
function openCloseProfile(id, name, overlay) {
|
||||
// Profil per Klick öffnen/schließen, alle anderen immer schließen
|
||||
|
||||
const profiles = document.getElementsByName(name); //Ausgewählter Profilbereich (visit, calendar, ...)
|
||||
const oProfile = document.getElementById(overlay); //Ausgewähltes Overlay
|
||||
const aProfile = document.getElementById(id); //Ausgewähltes Profil
|
||||
const aId = (id > 0) ? aProfile.id : 0; //Ausweichen, wenn kein Profil gewählt
|
||||
|
||||
console.log('id:' + id);
|
||||
console.log('overlay:' + overlay);
|
||||
console.log('name:' + name);
|
||||
|
||||
if (oProfile.style.display === "flex") { //Overlay ein-/ausblenden
|
||||
oProfile.style.display = "none";
|
||||
} else {
|
||||
oProfile.style.display = "flex";
|
||||
//TODO: folgender ScrollTop greift nicht, WARUM?
|
||||
//oProfile.scrollTop = 0; //Hinscrollen zum Beginn des Overlays, vor allem bei @Media
|
||||
}
|
||||
|
||||
for (let i = 0; i < profiles.length; i++) {
|
||||
|
||||
const cProfile = profiles[i]; //Aktuelles Profil (Style: profile_container)
|
||||
|
||||
if (cProfile.id === aId && cProfile.style.display !== "block") {
|
||||
profiles[i].style.display = "block";
|
||||
} else {
|
||||
profiles[i].style.display = "none";
|
||||
}
|
||||
}
|
||||
document.activeElement.blur(); //Fokus entfernen
|
||||
|
||||
// TEST console.log(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function mix(content) { //wird aktuell nicht eingesetzt, Daten werden per SQL randomized
|
||||
const list = document.getElementById(content);
|
||||
const items = Array.from(list.children);
|
||||
console.log('Vor dem Mischen:', items.map(item => item.textContent || item.innerText));
|
||||
|
||||
for (let i = items.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[items[i], items[j]] = [items[j], items[i]];
|
||||
}
|
||||
|
||||
console.log('Nach dem Mischen:', items.map(item => item.textContent || item.innerText));
|
||||
items.forEach(item => list.appendChild(item));
|
||||
}
|
||||
|
||||
|
||||
function showHideText(element) {
|
||||
element.classList.toggle("open");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Per Taste Overlay verlassen
|
||||
document.addEventListener('keydown', function(event) {
|
||||
const profileVisitOverlay = document.getElementById('profile_visit_overlay');
|
||||
const profileCalendarOverlay = document.getElementById('profile_calendar_overlay');
|
||||
const addNewUser = document.getElementById('addNewUser');
|
||||
const showMessage = document.getElementById('showMessage');
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
if (profileVisitOverlay && profileVisitOverlay.style.display === 'flex') {
|
||||
openCloseProfile(0, 'profile_visit', 'profile_visit_overlay');
|
||||
}
|
||||
if (profileCalendarOverlay && profileCalendarOverlay.style.display === 'flex') {
|
||||
openCloseProfile(0, 'profile_calendar', 'profile_calendar_overlay');
|
||||
}
|
||||
if (addNewUser && addNewUser.style.display === 'flex') {
|
||||
openCloseOverlay('addNewUser');
|
||||
}
|
||||
} else if (event.key === 'Enter' || event.key === 'Return' || event.key === " ") {
|
||||
if (showMessage && showMessage.style.display === 'flex') {
|
||||
openCloseOverlay('showMessage'); // ausblenden
|
||||
window.location.href=basisUrl; // zur aktuellen Seite zurückkehren
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Fokus auf passendes Element beim Laden der Intranet-Seiten
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
document.querySelector("#admintable tr[tabindex='0']")?.focus(); // Adminpanel
|
||||
document.querySelector("#visittable tr[tabindex='0']")?.focus(); // Besuchsstellen
|
||||
});
|
||||
@@ -0,0 +1,247 @@
|
||||
////==========================================//
|
||||
////GLOBALER BEREICH//
|
||||
////////////////////////////////////////////////
|
||||
////Globale Konstanten
|
||||
|
||||
////
|
||||
////////////////////////////////////////////////
|
||||
////==========================================//
|
||||
|
||||
|
||||
|
||||
////==========================================//
|
||||
////FUNKTIONEN und LISTENER//
|
||||
////////////////////////////////////////////////
|
||||
////
|
||||
|
||||
|
||||
// Warten, bis das DOM vollstaendig geladen ist
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var menuItems = document.querySelectorAll('.content-tab-bar__item[data-target]');
|
||||
|
||||
// Event-Listener fuer Klickereignisse auf Menueintraege
|
||||
menuItems.forEach(function(item) {
|
||||
item.addEventListener('click', function() {
|
||||
// Entferne die aktive Klasse von allen Menueintraegen
|
||||
menuItems.forEach(function(menuItem) {
|
||||
menuItem.classList.remove('active');
|
||||
});
|
||||
|
||||
// Fuege die aktive Klasse zum geklickten Menuelement hinzu
|
||||
item.classList.add('active');
|
||||
|
||||
// Verstecke alle Inhaltsbereiche
|
||||
document.querySelectorAll('.content_seelsorge').forEach(function(section) {
|
||||
section.classList.remove('active');
|
||||
});
|
||||
|
||||
// Zeige den entsprechenden Inhalt an
|
||||
var contentId = item.getAttribute('data-target');
|
||||
document.getElementById(contentId).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// ESC-Taste schliesst offene Modals
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
closeCalendarHelp();
|
||||
closeDayModal();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Wechsel der Kalenderblaetter Monat 1 und 2
|
||||
function switchCalendar(type) {
|
||||
const calendar_header_1 = document.querySelector('#calendar_header_1');
|
||||
const calendar_header_2 = document.querySelector('#calendar_header_2');
|
||||
const calendar_1 = document.querySelectorAll('[name="calendar_1"]');
|
||||
const calendar_2 = document.querySelectorAll('[name="calendar_2"]');
|
||||
|
||||
const isLeft = type === "left";
|
||||
calendar_header_1.style.display = isLeft ? "flex" : "none";
|
||||
calendar_header_2.style.display = isLeft ? "none" : "flex";
|
||||
|
||||
calendar_1.forEach(cal => cal.style.visibility = isLeft ? "visible" : "collapse");
|
||||
calendar_2.forEach(cal => cal.style.visibility = isLeft ? "collapse" : "visible");
|
||||
}
|
||||
|
||||
|
||||
// Tages-Modal oeffnen
|
||||
async function openDayModal(calendarDate) {
|
||||
if (!calendarDate) return;
|
||||
|
||||
const modal = document.getElementById('seelsorge-day-modal');
|
||||
const body = document.getElementById('modal-day-body');
|
||||
const title = document.getElementById('modal-day-title');
|
||||
const subtitle = document.getElementById('modal-day-subtitle');
|
||||
|
||||
if (!modal || !body || !title || !subtitle) {
|
||||
console.error('openDayModal: Modal-Elemente nicht gefunden.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Modal sofort anzeigen mit Ladezustand
|
||||
title.textContent = 'Laden...';
|
||||
subtitle.innerHTML = '';
|
||||
body.innerHTML = '<div class="seelsorge-modal-loading"><div class="loading-spinner"></div></div>';
|
||||
modal.style.display = 'flex';
|
||||
|
||||
try {
|
||||
const response = await fetch('content/calendar_day.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: 'calendarDate=' + encodeURIComponent(calendarDate)
|
||||
});
|
||||
|
||||
const html = await response.text();
|
||||
|
||||
if (response.ok) {
|
||||
body.innerHTML = html;
|
||||
|
||||
// Metadaten aus dem eingebetteten JSON lesen
|
||||
const metaEl = body.querySelector('#modal-meta');
|
||||
if (metaEl) {
|
||||
const meta = JSON.parse(metaEl.textContent);
|
||||
title.textContent = meta.title;
|
||||
|
||||
let chips = '<span class="seelsorge-modal-chip">KW ' + meta.kw + '</span>';
|
||||
if (meta.feiertag) {
|
||||
chips += '<span class="seelsorge-modal-chip seelsorge-chip-holiday">' + meta.feiertag + '</span>';
|
||||
}
|
||||
subtitle.innerHTML = chips;
|
||||
metaEl.remove();
|
||||
}
|
||||
} else {
|
||||
// PHP-Fehler direkt im Modal anzeigen
|
||||
title.textContent = 'Fehler ' + response.status;
|
||||
body.innerHTML = '<div style="padding:16px;font-family:monospace;font-size:0.85em;color:#d21400;white-space:pre-wrap;word-break:break-word;background:#fff5f5;border:1px solid #fcc;">'
|
||||
+ (html || 'Keine Antwort vom Server.') + '</div>';
|
||||
}
|
||||
} catch (error) {
|
||||
body.innerHTML = '<div class="seelsorge-modal-empty">Fehler beim Laden der Daten: ' + error.message + '</div>';
|
||||
console.error('Fehler beim Laden der Tagesdetails:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Modal schliessen
|
||||
function closeDayModal() {
|
||||
const modal = document.getElementById('seelsorge-day-modal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
// Backdrop-Klick schliesst Modal
|
||||
function closeDayModalOnBackdrop(event) {
|
||||
if (event.target === event.currentTarget) {
|
||||
closeDayModal();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Verfuegbarkeit im Modal togglen (Modal bleibt offen)
|
||||
async function toggleAvailabilityModal(date) {
|
||||
const btn = document.getElementById('modal-toggle-btn');
|
||||
if (!btn) return;
|
||||
|
||||
const originalText = btn.textContent;
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Wird gespeichert\u2026';
|
||||
|
||||
try {
|
||||
const response = await fetch("toggle_availability.php", {
|
||||
method: "POST",
|
||||
headers: { "Content-type": "application/x-www-form-urlencoded" },
|
||||
body: "date=" + encodeURIComponent(date)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.ok) {
|
||||
// Modal-Inhalt neu laden um aktuellen Stand zu zeigen
|
||||
await openDayModal(date);
|
||||
|
||||
// Kalender-Tageszelle visuell aktualisieren
|
||||
updateCalendarCell(date, data.nowAvailable, data.availCount);
|
||||
} else {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
console.error("Fehler:", data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
console.error("Fehler beim Aktualisieren der Verfuegbarkeit:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Kalender-Tageszelle visuell aktualisieren ohne Page-Reload
|
||||
function updateCalendarCell(date, nowAvailable, availCount) {
|
||||
var cells = document.querySelectorAll('#calendar_day_item');
|
||||
cells.forEach(function(cell) {
|
||||
var onclick = cell.getAttribute('onclick') || '';
|
||||
if (onclick.indexOf(date) === -1) return;
|
||||
|
||||
// Alle Verfuegbarkeits-Klassen entfernen
|
||||
cell.classList.remove('available_single', 'available_multiple', 'normalday');
|
||||
|
||||
if (availCount >= 2) {
|
||||
cell.classList.add('available_multiple');
|
||||
} else if (availCount === 1) {
|
||||
cell.classList.add('available_single');
|
||||
} else {
|
||||
cell.classList.add('normalday');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Profil eines Diakons aus dem Kalender-Modal oeffnen
|
||||
var _lastCalendarDate = null;
|
||||
|
||||
function openCalendarProfile(userId) {
|
||||
// Datum merken, damit wir beim Schliessen zurueckkehren koennen
|
||||
var metaEl = document.getElementById('modal-meta');
|
||||
var bodyEl = document.getElementById('modal-day-body');
|
||||
if (!_lastCalendarDate && bodyEl) {
|
||||
// Datum aus dem Toggle-Button extrahieren
|
||||
var toggleBtn = bodyEl.querySelector('#modal-toggle-btn');
|
||||
if (toggleBtn) {
|
||||
var onclickAttr = toggleBtn.getAttribute('onclick') || '';
|
||||
var match = onclickAttr.match(/'(\d{4}-\d{2}-\d{2})'/);
|
||||
if (match) _lastCalendarDate = match[1];
|
||||
}
|
||||
}
|
||||
closeDayModal();
|
||||
openCloseProfile(userId, 'profile_calendar', 'profile_calendar_overlay');
|
||||
}
|
||||
|
||||
// Globalen Listener fuer Kalender-Profil-Overlay: bei Schliessen Tagesmodal wieder oeffnen
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// MutationObserver auf das Kalender-Profil-Overlay
|
||||
var calOverlay = document.getElementById('profile_calendar_overlay');
|
||||
if (calOverlay) {
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(m) {
|
||||
if (m.attributeName === 'style' && calOverlay.style.display === 'none' && _lastCalendarDate) {
|
||||
var date = _lastCalendarDate;
|
||||
_lastCalendarDate = null;
|
||||
openDayModal(date);
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe(calOverlay, { attributes: true, attributeFilter: ['style'] });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Hilfe-Modal oeffnen/schliessen
|
||||
function openCalendarHelp() {
|
||||
var modal = document.getElementById('calendar-help-modal');
|
||||
if (modal) modal.style.display = 'flex';
|
||||
}
|
||||
function closeCalendarHelp() {
|
||||
var modal = document.getElementById('calendar-help-modal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* Zentrale Reiternavigation des Adminpanels.
|
||||
* Erwartet: $pdo (PDO) und optional $adminActiveTab.
|
||||
*/
|
||||
$adminActiveTab = $adminActiveTab ?? '';
|
||||
$adminInboxBadgeCount = 0;
|
||||
|
||||
try {
|
||||
$adminInboxBadgeCount = (int)$pdo->query("SELECT COUNT(*) FROM admin_messages WHERE status = 'pending'")->fetchColumn();
|
||||
} catch (Throwable $e) {
|
||||
// Die Navigation soll auch dann benutzbar bleiben, wenn das Postfach temporär nicht verfügbar ist.
|
||||
$adminInboxBadgeCount = 0;
|
||||
}
|
||||
|
||||
$adminTabs = [
|
||||
'users' => ['label' => 'Nutzerverwaltung', 'href' => 'admin.php'],
|
||||
'inbox' => ['label' => 'Postfach', 'href' => 'admin_inbox.php', 'badge' => $adminInboxBadgeCount],
|
||||
'kalli' => ['label' => 'Kalli', 'href' => 'admin_kalli.php'],
|
||||
'brandschutz' => ['label' => 'Brandschutz', 'href' => 'admin_brandschutz.php'],
|
||||
'notices' => ['label' => 'Meldungen', 'href' => 'admin_notices.php'],
|
||||
];
|
||||
?>
|
||||
<div class="content-tab-bar">
|
||||
<?php foreach ($adminTabs as $tabKey => $tab): ?>
|
||||
<a class="content-tab-bar__item<?= $adminActiveTab === $tabKey ? ' active' : '' ?>" href="<?= htmlspecialchars($tab['href'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<?= htmlspecialchars($tab['label'], ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php if (!empty($tab['badge'])): ?>
|
||||
<span class="content-tab-bar__badge"><?= (int)$tab['badge'] ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,677 @@
|
||||
<?php /* Name: admin_brandschutz.php
|
||||
Beschreibung: Brandschutz-Schulungsverwaltung im Adminpanel
|
||||
- Übersicht aller Nutzer mit Brandschutz-Rolle
|
||||
- Fälligkeitsstatus und Details
|
||||
- Manuelle Anpassung des Schulungsdatums */
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
|
||||
// Admin-Check
|
||||
$stmt = $pdo->prepare("SELECT \"Admin\" FROM user_permissions WHERE user_id = ?");
|
||||
$stmt->execute([$_SESSION["user_id"]]);
|
||||
$isAdmin = $stmt->fetchColumn();
|
||||
|
||||
if ((int)$isAdmin !== 1) {
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Hilfsfunktionen
|
||||
function getProfileImageUrl_bs(array $row, string $g_profilePicturePath): string {
|
||||
$profileImg = glob($g_profilePicturePath."{$row['user_id']}-*.jpg");
|
||||
if (!empty($profileImg)) {
|
||||
usort($profileImg, function($a, $b) {
|
||||
return filemtime($b) - filemtime($a);
|
||||
});
|
||||
return str_replace($_SERVER['DOCUMENT_ROOT'], '', $profileImg[0]);
|
||||
}
|
||||
return '/intranet_repo/general_files/profile_pictures/default.jpg';
|
||||
}
|
||||
|
||||
function getDisplayName_bs(array $row): string {
|
||||
$fullName = trim(($row['first_name'] ?? '') . ' ' . ($row['last_name'] ?? ''));
|
||||
return $fullName !== '' ? $fullName : ($row['mail'] ?? 'Unbekannt');
|
||||
}
|
||||
|
||||
// Schulungsdatum manuell anpassen (POST)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['bs_update_date'])) {
|
||||
$editUserId = (int)($_POST['bs_user_id'] ?? 0);
|
||||
$newDate = $_POST['bs_new_date'] ?? '';
|
||||
|
||||
if ($editUserId > 0 && preg_match('/^\d{4}-\d{2}-\d{2}$/', $newDate)) {
|
||||
// Prüfen ob das neue Datum innerhalb der Frist liegt (365 Tage ab Datum > heute)
|
||||
$newDueDate = date('Y-m-d', strtotime($newDate . ' +365 days'));
|
||||
$isWithinDeadline = (strtotime($newDueDate) >= strtotime(date('Y-m-d')));
|
||||
|
||||
if ($isWithinDeadline) {
|
||||
// Datum in der Frist: Zähler zurücksetzen
|
||||
$stmtUpsert = $pdo->prepare("INSERT INTO brandschutz_training (user_id, last_training_date, reminder_count, admin_reminder_count) VALUES (?, ?, 0, 0) ON CONFLICT (user_id) DO UPDATE SET last_training_date = EXCLUDED.last_training_date, reminder_count = 0, admin_reminder_count = 0");
|
||||
} else {
|
||||
// Datum außerhalb der Frist: Nur Datum aktualisieren, Zähler beibehalten
|
||||
$stmtUpsert = $pdo->prepare("INSERT INTO brandschutz_training (user_id, last_training_date, reminder_count, admin_reminder_count) VALUES (?, ?, 0, 0) ON CONFLICT (user_id) DO UPDATE SET last_training_date = EXCLUDED.last_training_date");
|
||||
}
|
||||
$stmtUpsert->execute([$editUserId, $newDate]);
|
||||
|
||||
// Systemnachricht in erledigte Admin-Nachrichten
|
||||
$adminName = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
|
||||
if (empty($adminName)) $adminName = 'Ein Administrator';
|
||||
|
||||
$stmtUser = $pdo->prepare("SELECT first_name, last_name, mail FROM user_general_information WHERE user_id = ?");
|
||||
$stmtUser->execute([$editUserId]);
|
||||
$editedUser = $stmtUser->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$editedName = trim(($editedUser['first_name'] ?? '') . ' ' . ($editedUser['last_name'] ?? ''));
|
||||
if (empty($editedName)) $editedName = $editedUser['mail'] ?? 'Unbekannt';
|
||||
|
||||
$formattedDate = date('d.m.Y', strtotime($newDate));
|
||||
$sysSubject = "Brandschutz-Schulungsdatum angepasst: {$editedName}";
|
||||
$sysMessage = "{$adminName} hat das Schulungsdatum von {$editedName} manuell auf den {$formattedDate} gesetzt.";
|
||||
|
||||
$stmtMsg = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())");
|
||||
$senderMail = $editedUser['mail'] ?? '';
|
||||
$stmtMsg->execute([$adminName, $senderMail, $sysSubject, $sysMessage]);
|
||||
|
||||
header("Location: admin_brandschutz.php?message=5");
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Brandschutz-Nutzer laden
|
||||
$sql = "SELECT ugi.user_id, ugi.first_name, ugi.last_name, ugi.mail,
|
||||
bt.last_training_date, bt.reminder_count, bt.admin_reminder_count,
|
||||
CASE WHEN ul.user_id IS NOT NULL THEN 1 ELSE 0 END AS IstRegistriert
|
||||
FROM user_permissions up
|
||||
INNER JOIN user_general_information ugi ON up.user_id = ugi.user_id
|
||||
LEFT JOIN brandschutz_training bt ON ugi.user_id = bt.user_id
|
||||
LEFT JOIN user_login ul ON ugi.user_id = ul.user_id
|
||||
WHERE up.\"Brandschutz\" = 1
|
||||
ORDER BY bt.last_training_date ASC, ugi.last_name ASC, ugi.first_name ASC";
|
||||
$bsUsers = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
<style>
|
||||
.admin-users-shell {
|
||||
padding: 18px;
|
||||
background: linear-gradient(135deg, var(--gray-50) 0%, var(--theme-light, var(--nak-blue-light)) 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
.admin-table-card {
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(120, 140, 160, 0.22);
|
||||
background: rgba(255,255,255,0.86);
|
||||
box-shadow: 0 20px 45px rgba(31, 38, 46, 0.10), 0 1px 0 rgba(255,255,255,0.9) inset;
|
||||
}
|
||||
.admin-list-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 16px 18px 12px 18px;
|
||||
border-bottom: 1px solid rgba(120, 140, 160, 0.16);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.72));
|
||||
}
|
||||
.admin-list-title {
|
||||
font-size: 1.05em;
|
||||
font-weight: 800;
|
||||
color: hsl(210, 20%, 15%);
|
||||
}
|
||||
.admin-list-hint {
|
||||
font-size: 0.86em;
|
||||
color: hsl(210, 15%, 46%);
|
||||
}
|
||||
table.admin-user-table {
|
||||
display: table !important;
|
||||
width: calc(100% - 24px);
|
||||
margin: 8px 12px 14px 12px;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 8px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
.admin-user-table thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding: 10px 14px;
|
||||
color: hsl(210, 16%, 46%);
|
||||
font-size: 0.78em;
|
||||
font-weight: 800;
|
||||
text-align: left;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
box-shadow: 0 6px 18px rgba(31, 38, 46, 0.06);
|
||||
transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row:hover {
|
||||
transform: translateY(-1px);
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 12px 26px rgba(31, 38, 46, 0.13);
|
||||
}
|
||||
.admin-user-table td {
|
||||
padding: 12px 14px !important;
|
||||
vertical-align: middle;
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row td:first-child {
|
||||
width: 82px;
|
||||
min-width: 82px;
|
||||
max-width: 82px;
|
||||
}
|
||||
.admin-profile-button {
|
||||
display: block;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8px 20px rgba(31, 38, 46, 0.18), 0 0 0 3px rgba(255,255,255,0.95);
|
||||
}
|
||||
.admin-profile-button img {
|
||||
display: block;
|
||||
width: 58px !important;
|
||||
height: 58px !important;
|
||||
object-fit: cover;
|
||||
border-radius: 12px !important;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row:hover .admin-profile-button img {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
.admin-user-name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 1em;
|
||||
font-weight: 800;
|
||||
color: hsl(210, 20%, 15%);
|
||||
}
|
||||
.bs-status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 10px;
|
||||
font-size: 0.78em;
|
||||
font-weight: 800;
|
||||
}
|
||||
.bs-status-ok {
|
||||
color: hsl(145, 50%, 28%);
|
||||
background: hsl(145, 50%, 93%);
|
||||
border: 1px solid hsl(145, 50%, 82%);
|
||||
}
|
||||
.bs-status-warning {
|
||||
color: hsl(35, 78%, 30%);
|
||||
background: hsl(42, 90%, 93%);
|
||||
border: 1px solid hsl(42, 90%, 78%);
|
||||
}
|
||||
.bs-status-overdue {
|
||||
color: hsl(0, 65%, 38%);
|
||||
background: hsl(0, 65%, 95%);
|
||||
border: 1px solid hsl(0, 65%, 82%);
|
||||
}
|
||||
.bs-status-critical {
|
||||
color: #FFFFFF;
|
||||
background: hsl(0, 65%, 45%);
|
||||
border: 1px solid hsl(0, 65%, 38%);
|
||||
}
|
||||
.bs-due-date {
|
||||
font-size: 0.9em;
|
||||
font-weight: 650;
|
||||
color: hsl(210, 14%, 35%);
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.admin-modal-card {
|
||||
position: relative;
|
||||
width: min(720px, calc(100vw - 24px));
|
||||
max-height: min(760px, calc(100vh - 24px));
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 24px 70px rgba(0,0,0,0.36);
|
||||
}
|
||||
.admin-modal-hero {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 112px 1fr;
|
||||
gap: 18px;
|
||||
align-items: center;
|
||||
padding: 24px;
|
||||
color: #FFFFFF;
|
||||
background:
|
||||
radial-gradient(circle at 10% 0%, rgba(255,255,255,0.24), transparent 32%),
|
||||
linear-gradient(135deg, hsl(25, 90%, 45%), hsl(25, 95%, 35%));
|
||||
}
|
||||
.admin-modal-profile-img {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
object-fit: cover;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 12px 28px rgba(0,0,0,0.32), 0 0 0 4px rgba(255,255,255,0.18);
|
||||
}
|
||||
.admin-modal-title {
|
||||
margin: 0 42px 6px 0;
|
||||
font-size: 1.45em;
|
||||
font-weight: 850;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.admin-modal-subtitle {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
color: rgba(255,255,255,0.86);
|
||||
font-weight: 600;
|
||||
}
|
||||
.admin-modal-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4px 9px;
|
||||
border-radius: 9999px;
|
||||
background: rgba(255,255,255,0.14);
|
||||
border: 1px solid rgba(255,255,255,0.18);
|
||||
font-size: 0.82em;
|
||||
}
|
||||
.admin-modal-body {
|
||||
padding: 22px 24px 24px 24px;
|
||||
}
|
||||
.admin-section-title {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 0.9em;
|
||||
font-weight: 850;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: hsl(210, 18%, 36%);
|
||||
}
|
||||
.admin-modal-card .exit {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 14px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border: 1px solid rgba(255,255,255,0.25);
|
||||
background: rgba(255,255,255,0.16);
|
||||
color: #FFFFFF;
|
||||
font-size: 1.35em;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bs-detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.bs-detail-card {
|
||||
padding: 14px 16px;
|
||||
border: 1px solid hsl(210, 18%, 88%);
|
||||
background: linear-gradient(180deg, #FFFFFF, hsl(210, 12%, 98%));
|
||||
}
|
||||
.bs-detail-label {
|
||||
margin-bottom: 3px;
|
||||
color: hsl(210, 14%, 46%);
|
||||
font-size: 0.74em;
|
||||
font-weight: 850;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.bs-detail-value {
|
||||
color: hsl(210, 20%, 18%);
|
||||
font-size: 1.02em;
|
||||
font-weight: 850;
|
||||
}
|
||||
.bs-detail-value.overdue {
|
||||
color: hsl(0, 65%, 42%);
|
||||
}
|
||||
.bs-detail-value.ok {
|
||||
color: hsl(145, 50%, 32%);
|
||||
}
|
||||
.admin-modal-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 10px;
|
||||
border-top: 1px solid hsl(210, 18%, 90%);
|
||||
padding-top: 16px;
|
||||
}
|
||||
.admin-modal-actions button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 36px;
|
||||
padding: 8px 13px;
|
||||
border: 1px solid hsl(210, 18%, 84%);
|
||||
background: #FFFFFF;
|
||||
color: hsl(210, 20%, 22%);
|
||||
font-size: 0.86em;
|
||||
font-weight: 850;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 12px rgba(31,38,46,0.06);
|
||||
}
|
||||
.admin-modal-actions button:hover {
|
||||
background: hsl(210, 57%, 96%);
|
||||
}
|
||||
.admin-save-button {
|
||||
color: #FFFFFF !important;
|
||||
background: linear-gradient(135deg, var(--nak-orange), hsl(25, 95%, 40%)) !important;
|
||||
border-color: hsl(25, 95%, 40%) !important;
|
||||
}
|
||||
.bs-date-input {
|
||||
padding: 10px 12px;
|
||||
font-size: var(--font-size-sm);
|
||||
font-family: var(--font-primary);
|
||||
border: 1px solid var(--gray-300);
|
||||
background: var(--gray-50);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-weight: 650;
|
||||
}
|
||||
.bs-date-input:focus {
|
||||
border-color: hsl(25, 80%, 55%);
|
||||
background: #FFFFFF;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 4px hsla(25, 80%, 55%, 0.14);
|
||||
}
|
||||
|
||||
@media (max-width: 780px) {
|
||||
.admin-users-shell { padding: 10px; }
|
||||
.admin-list-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 14px;
|
||||
gap: 8px;
|
||||
}
|
||||
table.admin-user-table {
|
||||
display: block !important;
|
||||
width: auto;
|
||||
margin: 8px;
|
||||
}
|
||||
.admin-user-table thead { display: none; }
|
||||
.admin-user-table tbody {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row {
|
||||
display: grid;
|
||||
grid-template-columns: 72px minmax(0, 1fr);
|
||||
gap: 0 12px;
|
||||
padding: 12px;
|
||||
border: 1px solid rgba(120, 140, 160, 0.16);
|
||||
box-shadow: 0 8px 22px rgba(31, 38, 46, 0.08);
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row td {
|
||||
display: block;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.admin-user-table tbody tr.admin-user-row td:first-child {
|
||||
grid-row: 1 / span 3;
|
||||
width: 72px;
|
||||
min-width: 72px;
|
||||
max-width: 72px;
|
||||
}
|
||||
.admin-profile-button,
|
||||
.admin-profile-button img {
|
||||
width: 64px !important;
|
||||
height: 64px !important;
|
||||
border-radius: 12px !important;
|
||||
}
|
||||
.admin-modal-card {
|
||||
width: calc(100vw - 12px);
|
||||
max-height: calc(100dvh - 12px);
|
||||
}
|
||||
.admin-modal-hero {
|
||||
grid-template-columns: 78px minmax(0, 1fr);
|
||||
gap: 14px;
|
||||
padding: 18px;
|
||||
}
|
||||
.admin-modal-profile-img {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
border-radius: 14px;
|
||||
}
|
||||
.admin-modal-title {
|
||||
font-size: 1.15em;
|
||||
margin-right: 40px;
|
||||
}
|
||||
.admin-modal-body { padding: 18px; }
|
||||
.bs-detail-grid { grid-template-columns: 1fr; }
|
||||
.admin-modal-actions { flex-direction: column-reverse; }
|
||||
.admin-modal-actions button { width: 100%; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="theme-admin">
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
|
||||
|
||||
<?php include $g_phpSnippetsPath.'overlay_message.php'; ?>
|
||||
|
||||
<div class="header_title ht_admin text_white unselectable" id="header_title">
|
||||
<span class="header_title_text">Adminpanel</span>
|
||||
</div>
|
||||
|
||||
<div class="content" id="fullsize">
|
||||
<?php $adminActiveTab = 'brandschutz'; require __DIR__.'/_tabs.php'; ?>
|
||||
|
||||
<div class="admin-users-shell">
|
||||
<div class="admin-table-card">
|
||||
<div class="admin-list-header">
|
||||
<div>
|
||||
<span class="admin-list-title">Brandschutz-Schulungen</span>
|
||||
<div class="admin-list-hint"><?= count($bsUsers) ?> Nutzer mit Brandschutz-Rolle</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="admin-user-table" id="bsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Profil</th>
|
||||
<th>Name</th>
|
||||
<th>Nächste Fälligkeit</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($bsUsers as $bsUser): ?>
|
||||
<?php
|
||||
$nameOutput = getDisplayName_bs($bsUser);
|
||||
$profileUrl = getProfileImageUrl_bs($bsUser, $g_profilePicturePath);
|
||||
|
||||
$lastTraining = $bsUser['last_training_date'];
|
||||
$reminderCount = (int)($bsUser['reminder_count'] ?? 0);
|
||||
$adminReminderCount = (int)($bsUser['admin_reminder_count'] ?? 0);
|
||||
|
||||
// Berechne Fälligkeit
|
||||
if (empty($lastTraining)) {
|
||||
$dueDate = null;
|
||||
$daysOverdue = null;
|
||||
$statusText = 'Nie geschult';
|
||||
$statusClass = 'bs-status-overdue';
|
||||
$dueDateDisplay = 'Sofort fällig';
|
||||
} else {
|
||||
$dueDate = date('Y-m-d', strtotime($lastTraining . ' +365 days'));
|
||||
$today = date('Y-m-d');
|
||||
$diff = (strtotime($dueDate) - strtotime($today)) / 86400;
|
||||
|
||||
if ($diff > 30) {
|
||||
$statusText = 'Aktuell';
|
||||
$statusClass = 'bs-status-ok';
|
||||
$dueDateDisplay = date('d.m.Y', strtotime($dueDate));
|
||||
} elseif ($diff > 0) {
|
||||
$statusText = 'Bald fällig';
|
||||
$statusClass = 'bs-status-warning';
|
||||
$dueDateDisplay = date('d.m.Y', strtotime($dueDate));
|
||||
} elseif ($diff > -120) {
|
||||
$daysOverdue = abs((int)$diff);
|
||||
$statusText = "{$daysOverdue} Tage überfällig";
|
||||
$statusClass = 'bs-status-overdue';
|
||||
$dueDateDisplay = date('d.m.Y', strtotime($dueDate));
|
||||
} else {
|
||||
$daysOverdue = abs((int)$diff);
|
||||
$statusText = "{$daysOverdue} Tage überfällig";
|
||||
$statusClass = 'bs-status-critical';
|
||||
$dueDateDisplay = date('d.m.Y', strtotime($dueDate));
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr class="admin-user-row" tabindex="0" role="button" aria-label="<?= htmlspecialchars($nameOutput) ?> Details" onclick="openBsModal(<?= (int)$bsUser['user_id'] ?>)" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();openBsModal(<?= (int)$bsUser['user_id'] ?>)}">
|
||||
<td>
|
||||
<button class="admin-profile-button" type="button" tabindex="-1" aria-hidden="true">
|
||||
<img src="<?= htmlspecialchars($profileUrl) ?>" alt="Profilbild von <?= htmlspecialchars($nameOutput) ?>">
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<span class="admin-user-name"><?= htmlspecialchars($nameOutput) ?></span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="bs-due-date"><?= $dueDateDisplay ?></span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="bs-status-badge <?= $statusClass ?>"><?= $statusText ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($bsUsers)): ?>
|
||||
<tr><td colspan="4" style="padding:24px !important;text-align:center;color:hsl(210,20%,45%);background:#FFF !important;">Keine Nutzer mit der Rolle "Brandschutz" gefunden.</td></tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modals für jeden Brandschutz-Nutzer -->
|
||||
<?php foreach ($bsUsers as $bsUser): ?>
|
||||
<?php
|
||||
$nameOutput = getDisplayName_bs($bsUser);
|
||||
$profileUrl = getProfileImageUrl_bs($bsUser, $g_profilePicturePath);
|
||||
$lastTraining = $bsUser['last_training_date'];
|
||||
$reminderCount = (int)($bsUser['reminder_count'] ?? 0);
|
||||
$adminReminderCount = (int)($bsUser['admin_reminder_count'] ?? 0);
|
||||
|
||||
if (empty($lastTraining)) {
|
||||
$dueDate = null;
|
||||
$dueDateDisplay = 'Sofort fällig';
|
||||
$lastTrainingDisplay = 'Nie';
|
||||
$overdueText = 'Keine Schulung hinterlegt – sofort fällig';
|
||||
$overdueClass = 'overdue';
|
||||
} else {
|
||||
$dueDate = date('Y-m-d', strtotime($lastTraining . ' +365 days'));
|
||||
$dueDateDisplay = date('d.m.Y', strtotime($dueDate));
|
||||
$lastTrainingDisplay = date('d.m.Y', strtotime($lastTraining));
|
||||
$today = date('Y-m-d');
|
||||
$diff = (strtotime($dueDate) - strtotime($today)) / 86400;
|
||||
|
||||
if ($diff > 0) {
|
||||
$overdueText = 'Nicht überfällig (' . (int)$diff . ' Tage verbleibend)';
|
||||
$overdueClass = 'ok';
|
||||
} else {
|
||||
$daysOverdue = abs((int)$diff);
|
||||
$overdueText = "{$daysOverdue} Tage überfällig";
|
||||
$overdueClass = 'overdue';
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div class="standard_overlay" id="bsModal-<?= (int)$bsUser['user_id'] ?>" onclick="if(event.target.id==='bsModal-<?= (int)$bsUser['user_id'] ?>')closeBsModal(<?= (int)$bsUser['user_id'] ?>)">
|
||||
<div class="admin-modal-card">
|
||||
<button type="button" class="exit" aria-label="Schließen" onclick="closeBsModal(<?= (int)$bsUser['user_id'] ?>)">×</button>
|
||||
|
||||
<div class="admin-modal-hero">
|
||||
<img class="admin-modal-profile-img" src="<?= htmlspecialchars($profileUrl) ?>" alt="Profilbild von <?= htmlspecialchars($nameOutput) ?>">
|
||||
<div>
|
||||
<div class="admin-modal-title"><?= htmlspecialchars($nameOutput) ?></div>
|
||||
<div class="admin-modal-subtitle">
|
||||
<span><?= htmlspecialchars($bsUser['mail'] ?? '') ?></span>
|
||||
<span class="admin-modal-chip">Brandschutz</span>
|
||||
</div>
|
||||
<div class="admin-modal-subtitle" style="margin-bottom:0;">Schulungsdetails & Fälligkeiten</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-modal-body">
|
||||
<div class="admin-section-title">Schulungsstatus</div>
|
||||
<div class="bs-detail-grid">
|
||||
<div class="bs-detail-card">
|
||||
<div class="bs-detail-label">Letzte Schulung</div>
|
||||
<div class="bs-detail-value"><?= $lastTrainingDisplay ?></div>
|
||||
</div>
|
||||
<div class="bs-detail-card">
|
||||
<div class="bs-detail-label">Nächste Fälligkeit</div>
|
||||
<div class="bs-detail-value"><?= $dueDateDisplay ?></div>
|
||||
</div>
|
||||
<div class="bs-detail-card">
|
||||
<div class="bs-detail-label">Überfälligkeit</div>
|
||||
<div class="bs-detail-value <?= $overdueClass ?>"><?= $overdueText ?></div>
|
||||
</div>
|
||||
<div class="bs-detail-card">
|
||||
<div class="bs-detail-label">Erinnerungsmails gesendet</div>
|
||||
<div class="bs-detail-value"><?= $reminderCount ?></div>
|
||||
</div>
|
||||
<?php if ($adminReminderCount > 0): ?>
|
||||
<div class="bs-detail-card">
|
||||
<div class="bs-detail-label">Admin-Eskalationen</div>
|
||||
<div class="bs-detail-value overdue"><?= $adminReminderCount ?></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="admin-section-title">Schulungsdatum anpassen</div>
|
||||
<form method="post" action="">
|
||||
<input type="hidden" name="bs_user_id" value="<?= (int)$bsUser['user_id'] ?>">
|
||||
<div style="display:flex;gap:10px;align-items:flex-end;margin-bottom:8px;">
|
||||
<div style="flex:1;">
|
||||
<label style="display:block;font-size:var(--font-size-xs);font-weight:600;color:var(--gray-600);margin-bottom:4px;">Datum der letzten Schulung</label>
|
||||
<input type="date" name="bs_new_date" class="bs-date-input" value="<?= htmlspecialchars($lastTraining ?? '') ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin:0 0 16px 0;font-size:0.82em;color:hsl(210,14%,46%);font-weight:600;">Setzt das Schulungsdatum und alle Erinnerungszähler zurück.</p>
|
||||
|
||||
<div class="admin-modal-actions">
|
||||
<div>
|
||||
<button type="button" onclick="closeBsModal(<?= (int)$bsUser['user_id'] ?>)">Schließen</button>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" name="bs_update_date" value="1" class="admin-save-button">Datum speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div><!-- content -->
|
||||
|
||||
<script>
|
||||
function openBsModal(userId) {
|
||||
var modal = document.getElementById('bsModal-' + userId);
|
||||
if (modal) modal.style.display = 'flex';
|
||||
}
|
||||
function closeBsModal(userId) {
|
||||
var modal = document.getElementById('bsModal-' + userId);
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
document.querySelectorAll('.standard_overlay[id^="bsModal-"]').forEach(function(m) {
|
||||
m.style.display = 'none';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,564 @@
|
||||
<?php /* Name: admin_inbox.php
|
||||
Beschreibung: Admin-Nachrichteninbox
|
||||
- Registrierungsanfragen
|
||||
- Kontaktformular-Anfragen
|
||||
- Systemnachrichten
|
||||
- Seelsorge-Nachrichten
|
||||
- Info-Nachrichten */
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
|
||||
// Admin-Check
|
||||
$stmt = $pdo->prepare("SELECT \"Admin\" FROM user_permissions WHERE user_id = ?");
|
||||
$stmt->execute([$_SESSION["user_id"]]);
|
||||
$isAdmin = $stmt->fetchColumn();
|
||||
|
||||
if ((int)$isAdmin !== 1) {
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Typ-Konfiguration für Inbox
|
||||
$typeConfig = [
|
||||
'registration' => ['label' => 'Registrierung', 'class' => 'inbox-type-registration'],
|
||||
'contact' => ['label' => 'Kontakt', 'class' => 'inbox-type-contact'],
|
||||
'system' => ['label' => 'System', 'class' => 'inbox-type-system'],
|
||||
];
|
||||
|
||||
// Filter
|
||||
$activeFilter = $_GET['filter'] ?? 'all';
|
||||
$validFilters = array_merge(['all'], array_keys($typeConfig));
|
||||
if (!in_array($activeFilter, $validFilters, true)) $activeFilter = 'all';
|
||||
|
||||
function getTypeLabel($type, $typeConfig) {
|
||||
return $typeConfig[$type]['label'] ?? ucfirst($type);
|
||||
}
|
||||
function getTypeClass($type, $typeConfig) {
|
||||
return $typeConfig[$type]['class'] ?? 'inbox-type-system';
|
||||
}
|
||||
|
||||
// Kontaktnachricht als erledigt markieren
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["mark_done"])) {
|
||||
$msgId = (int)$_POST["mark_done"];
|
||||
$stmt = $pdo->prepare("UPDATE admin_messages SET status = 'done', processed_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$msgId]);
|
||||
header("Location: admin_inbox.php?inbox_status=done");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Brandschutz-Eskalation: Admin bestätigt persönliche Erinnerung
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["bs_escalation_confirm"])) {
|
||||
$msgId = (int)$_POST["bs_escalation_msg_id"];
|
||||
$bsUserId = (int)$_POST["bs_escalation_user_id"];
|
||||
|
||||
// Nachricht als erledigt markieren
|
||||
$stmt = $pdo->prepare("UPDATE admin_messages SET status = 'done', processed_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$msgId]);
|
||||
|
||||
// Log-Eintrag erstellen
|
||||
$adminName = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
|
||||
if (empty($adminName)) $adminName = 'Ein Administrator';
|
||||
|
||||
$stmtUser = $pdo->prepare("SELECT first_name, last_name, mail FROM user_general_information WHERE user_id = ?");
|
||||
$stmtUser->execute([$bsUserId]);
|
||||
$bsUserData = $stmtUser->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$bsUserName = trim(($bsUserData['first_name'] ?? '') . ' ' . ($bsUserData['last_name'] ?? ''));
|
||||
if (empty($bsUserName)) $bsUserName = $bsUserData['mail'] ?? 'Unbekannt';
|
||||
|
||||
$logSubject = "Persönliche Brandschutz-Erinnerung bestätigt: {$bsUserName}";
|
||||
$logMessage = "{$adminName} hat bestätigt, {$bsUserName} persönlich an die ausstehende Brandschutzunterweisung erinnert zu haben.";
|
||||
|
||||
$stmtLog = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())");
|
||||
$senderMail = $bsUserData['mail'] ?? '';
|
||||
$stmtLog->execute([$adminName, $senderMail, $logSubject, $logMessage]);
|
||||
|
||||
header("Location: admin_inbox.php?inbox_status=done");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Nachrichten laden (mit optionalem Filter)
|
||||
$filterClause = '';
|
||||
if ($activeFilter !== 'all') {
|
||||
$filterClause = " AND type = '" . $activeFilter . "'";
|
||||
}
|
||||
$pendingMessages = $pdo->query("SELECT * FROM admin_messages WHERE status = 'pending'{$filterClause} ORDER BY created_at DESC")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$doneMessages = $pdo->query("SELECT * FROM admin_messages WHERE status = 'done'{$filterClause} ORDER BY processed_at DESC LIMIT 20")->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
// Rollen laden für Registrierungs-Modal
|
||||
$permissionRoles = [];
|
||||
$rolesResult = $pdo->query("SELECT column_name FROM information_schema.columns WHERE table_name = 'user_permissions' AND table_schema = 'public'");
|
||||
while ($col = $rolesResult->fetch(PDO::FETCH_ASSOC)) {
|
||||
if (!in_array($col['column_name'], ['p_id', 'user_id'], true)) {
|
||||
$permissionRoles[] = $col['column_name'];
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
<style>
|
||||
.inbox-shell {
|
||||
padding: 18px;
|
||||
background: linear-gradient(135deg, var(--gray-50) 0%, var(--theme-light, var(--nak-blue-light)) 100%);
|
||||
min-height: 100%;
|
||||
}
|
||||
.inbox-card {
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(120, 140, 160, 0.22);
|
||||
background: rgba(255,255,255,0.86);
|
||||
box-shadow: 0 20px 45px rgba(31, 38, 46, 0.10), 0 1px 0 rgba(255,255,255,0.9) inset;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.inbox-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 18px 12px 18px;
|
||||
border-bottom: 1px solid rgba(120, 140, 160, 0.16);
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.72));
|
||||
}
|
||||
.inbox-title {
|
||||
font-size: 1.05em;
|
||||
font-weight: 800;
|
||||
color: hsl(210, 20%, 15%);
|
||||
}
|
||||
.inbox-count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 24px;
|
||||
height: 24px;
|
||||
padding: 0 7px;
|
||||
background: hsl(0, 78%, 47%);
|
||||
color: #FFFFFF;
|
||||
font-size: 0.78em;
|
||||
font-weight: 850;
|
||||
}
|
||||
.inbox-item {
|
||||
padding: 16px 18px;
|
||||
border-bottom: 1px solid rgba(120, 140, 160, 0.1);
|
||||
transition: background 0.18s ease;
|
||||
}
|
||||
.inbox-item:last-child { border-bottom: none; }
|
||||
.inbox-item:hover { background: hsl(210, 57%, 97%); }
|
||||
.inbox-item-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.inbox-item-type {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
font-size: 0.72em;
|
||||
font-weight: 800;
|
||||
}
|
||||
.inbox-type-registration {
|
||||
color: hsl(210, 57%, 34%);
|
||||
background: hsl(210, 57%, 94%);
|
||||
border: 1px solid hsl(210, 57%, 88%);
|
||||
}
|
||||
.inbox-type-contact {
|
||||
color: hsl(145, 50%, 32%);
|
||||
background: hsl(145, 50%, 93%);
|
||||
border: 1px solid hsl(145, 50%, 85%);
|
||||
}
|
||||
.inbox-type-system {
|
||||
color: hsl(30, 70%, 36%);
|
||||
background: hsl(30, 70%, 94%);
|
||||
border: 1px solid hsl(30, 70%, 85%);
|
||||
}
|
||||
|
||||
.inbox-item-date {
|
||||
font-size: 0.82em;
|
||||
color: hsl(210, 14%, 50%);
|
||||
font-weight: 600;
|
||||
}
|
||||
.inbox-item-subject {
|
||||
font-weight: 800;
|
||||
color: hsl(210, 20%, 15%);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.inbox-item-sender {
|
||||
font-size: 0.9em;
|
||||
color: hsl(210, 14%, 40%);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.inbox-item-message {
|
||||
font-size: 0.9em;
|
||||
color: hsl(210, 12%, 35%);
|
||||
white-space: pre-wrap;
|
||||
background: hsl(210, 12%, 98%);
|
||||
padding: 10px 12px;
|
||||
border: 1px solid hsl(210, 12%, 92%);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.inbox-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.inbox-actions form { display: inline; }
|
||||
.inbox-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 32px;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid hsl(210, 18%, 84%);
|
||||
background: #FFFFFF;
|
||||
color: hsl(210, 20%, 22%);
|
||||
font-size: 0.82em;
|
||||
font-weight: 850;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
box-shadow: 0 4px 12px rgba(31,38,46,0.06);
|
||||
transition: background 0.18s ease;
|
||||
}
|
||||
.inbox-btn:hover { background: hsl(210, 57%, 96%); }
|
||||
.inbox-btn-approve {
|
||||
color: #FFFFFF !important;
|
||||
background: linear-gradient(135deg, var(--nak-darkgreen), #005a10) !important;
|
||||
border-color: #005a10 !important;
|
||||
}
|
||||
.inbox-btn-reject {
|
||||
color: var(--nak-red) !important;
|
||||
border-color: hsl(352, 72%, 88%) !important;
|
||||
background: hsl(352, 72%, 97%) !important;
|
||||
}
|
||||
.inbox-btn-done {
|
||||
color: hsl(210, 14%, 46%) !important;
|
||||
background: hsl(210, 12%, 95%) !important;
|
||||
border-color: hsl(210, 12%, 88%) !important;
|
||||
}
|
||||
.inbox-empty {
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
color: hsl(210, 14%, 50%);
|
||||
font-weight: 600;
|
||||
}
|
||||
.inbox-section-title {
|
||||
margin: 18px 0 10px 0;
|
||||
font-size: 0.88em;
|
||||
font-weight: 850;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
color: hsl(210, 14%, 46%);
|
||||
}
|
||||
.inbox-done-item {
|
||||
opacity: 0.6;
|
||||
}
|
||||
@media (max-width: 780px) {
|
||||
.inbox-shell { padding: 10px; }
|
||||
.inbox-item-header { flex-direction: column; align-items: flex-start; gap: 4px; }
|
||||
.inbox-filter-bar { gap: 6px; }
|
||||
.inbox-filter-btn { font-size: 0.72em; padding: 5px 10px; }
|
||||
}
|
||||
.inbox-filter-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.inbox-filter-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 6px 14px;
|
||||
border: 1px solid hsl(210, 18%, 84%);
|
||||
background: #FFF;
|
||||
color: hsl(210, 18%, 42%);
|
||||
font-size: 0.82em;
|
||||
font-weight: 750;
|
||||
cursor: pointer;
|
||||
transition: all 0.18s ease;
|
||||
text-decoration: none;
|
||||
}
|
||||
.inbox-filter-btn:hover { background: hsl(210, 57%, 96%); }
|
||||
.inbox-filter-btn.active {
|
||||
background: hsl(210, 57%, 94%);
|
||||
border-color: hsl(210, 57%, 72%);
|
||||
color: hsl(210, 57%, 30%);
|
||||
font-weight: 850;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="theme-admin">
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
|
||||
|
||||
<?php include $g_phpSnippetsPath.'overlay_message.php'; ?>
|
||||
|
||||
<?php if (isset($_GET["inbox_status"])): ?>
|
||||
<?php
|
||||
$inboxStatusMap = [
|
||||
'done' => ['type' => 'success', 'text' => 'Nachricht als erledigt markiert.'],
|
||||
'approved' => ['type' => 'success', 'text' => 'Registrierung freigegeben.'],
|
||||
'rejected' => ['type' => 'success', 'text' => 'Registrierung abgelehnt.'],
|
||||
'error' => ['type' => 'error', 'text' => 'Ein Fehler ist aufgetreten.'],
|
||||
];
|
||||
$statusKey = $_GET["inbox_status"];
|
||||
$statusInfo = $inboxStatusMap[$statusKey] ?? ['type' => 'success', 'text' => 'Aktion ausgeführt.'];
|
||||
?>
|
||||
<div class="nak-toast nak-toast--<?= $statusInfo['type'] ?>" id="nakToast">
|
||||
<div class="nak-toast__icon">
|
||||
<?php if ($statusInfo['type'] === 'success'): ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
<?php else: ?>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<span class="nak-toast__text"><?= htmlspecialchars($statusInfo['text']) ?></span>
|
||||
<button class="nak-toast__close" onclick="dismissNakToast()" aria-label="Schließen">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var toast = document.getElementById('nakToast');
|
||||
if (!toast) return;
|
||||
requestAnimationFrame(function() { toast.classList.add('nak-toast--visible'); });
|
||||
var timer = setTimeout(function() { dismissNakToast(); }, 4000);
|
||||
toast._timer = timer;
|
||||
if (window.history && window.history.replaceState) {
|
||||
window.history.replaceState({}, '', 'admin_inbox.php');
|
||||
}
|
||||
})();
|
||||
function dismissNakToast() {
|
||||
var toast = document.getElementById('nakToast');
|
||||
if (!toast || toast.classList.contains('nak-toast--hiding')) return;
|
||||
clearTimeout(toast._timer);
|
||||
toast.classList.add('nak-toast--hiding');
|
||||
toast.classList.remove('nak-toast--visible');
|
||||
setTimeout(function() { toast.remove(); }, 350);
|
||||
}
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="header_title ht_admin text_white" id="header_title">
|
||||
<span class="header_title_text">Adminpanel</span>
|
||||
</div>
|
||||
|
||||
<div class="content" id="fullsize">
|
||||
<?php $adminActiveTab = 'inbox'; require __DIR__.'/_tabs.php'; ?>
|
||||
<div class="inbox-shell">
|
||||
|
||||
<!-- Filter-Leiste -->
|
||||
<div class="inbox-filter-bar">
|
||||
<a href="?filter=all" class="inbox-filter-btn <?= $activeFilter === 'all' ? 'active' : '' ?>">Alle</a>
|
||||
<?php foreach ($typeConfig as $typeKey => $typeCfg): ?>
|
||||
<a href="?filter=<?= $typeKey ?>" class="inbox-filter-btn <?= $activeFilter === $typeKey ? 'active' : '' ?>"><?= $typeCfg['label'] ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Offene Nachrichten -->
|
||||
<div class="inbox-card">
|
||||
<div class="inbox-header">
|
||||
<div class="inbox-title">Offene Anfragen</div>
|
||||
<?php if (count($pendingMessages) > 0): ?>
|
||||
<span class="inbox-count"><?= count($pendingMessages) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (count($pendingMessages) === 0): ?>
|
||||
<div class="inbox-empty">Keine offenen Anfragen vorhanden.</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($pendingMessages as $msg): ?>
|
||||
<div class="inbox-item">
|
||||
<div class="inbox-item-header">
|
||||
<div>
|
||||
<span class="inbox-item-type <?= getTypeClass($msg['type'], $typeConfig) ?>">
|
||||
<?= getTypeLabel($msg['type'], $typeConfig) ?>
|
||||
</span>
|
||||
</div>
|
||||
<span class="inbox-item-date"><?= date('d.m.Y, H:i', strtotime($msg['created_at'])) ?> Uhr</span>
|
||||
</div>
|
||||
<div class="inbox-item-subject"><?= htmlspecialchars($msg['subject'] ?? '') ?></div>
|
||||
<div class="inbox-item-sender">
|
||||
Von: <?= htmlspecialchars($msg['sender_name'] ?? 'Unbekannt') ?>
|
||||
(<?= htmlspecialchars($msg['sender_email'] ?? '') ?>)
|
||||
</div>
|
||||
<div class="inbox-item-message"><?= htmlspecialchars($msg['message'] ?? '') ?></div>
|
||||
|
||||
<div class="inbox-actions">
|
||||
<?php if ($msg['type'] === 'registration'): ?>
|
||||
<?php $data = json_decode($msg['data_json'], true); ?>
|
||||
<button type="button" class="inbox-btn inbox-btn-approve" onclick="openRegistrationModal(<?= (int)($data['pending_id'] ?? 0) ?>, <?= (int)$msg['id'] ?>, '<?= htmlspecialchars($msg['sender_name'] ?? '', ENT_QUOTES) ?>', '<?= htmlspecialchars($msg['sender_email'] ?? '', ENT_QUOTES) ?>')">Anfrage bearbeiten</button>
|
||||
<?php elseif ($msg['type'] === 'system' && !empty($msg['data_json'])): ?>
|
||||
<?php
|
||||
$data = json_decode($msg['data_json'], true);
|
||||
if (isset($data['action']) && $data['action'] === 'brandschutz_escalation'):
|
||||
?>
|
||||
<button type="button" class="inbox-btn inbox-btn-approve" style="background:linear-gradient(135deg,var(--nak-orange),hsl(25,95%,40%)) !important;border-color:hsl(25,95%,40%) !important;" onclick="openBsEscalationModal(<?= (int)$msg['id'] ?>, <?= (int)$data['user_id'] ?>, '<?= htmlspecialchars($data['user_name'] ?? '', ENT_QUOTES) ?>', <?= (int)($data['days_overdue'] ?? 0) ?>)">Persönliche Erinnerung bestätigen</button>
|
||||
<?php else: ?>
|
||||
<form method="post" action="">
|
||||
<input type="hidden" name="mark_done" value="<?= (int)$msg['id'] ?>">
|
||||
<button type="submit" class="inbox-btn inbox-btn-done">Als erledigt markieren</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<form method="post" action="">
|
||||
<input type="hidden" name="mark_done" value="<?= (int)$msg['id'] ?>">
|
||||
<button type="submit" class="inbox-btn inbox-btn-done">Als erledigt markieren</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Erledigte Nachrichten -->
|
||||
<?php if (count($doneMessages) > 0): ?>
|
||||
<div class="inbox-section-title">Erledigte Anfragen (letzte 20)</div>
|
||||
<div class="inbox-card">
|
||||
<?php foreach ($doneMessages as $msg): ?>
|
||||
<div class="inbox-item inbox-done-item">
|
||||
<div class="inbox-item-header">
|
||||
<div>
|
||||
<span class="inbox-item-type <?= getTypeClass($msg['type'], $typeConfig) ?>">
|
||||
<?= getTypeLabel($msg['type'], $typeConfig) ?>
|
||||
</span>
|
||||
</div>
|
||||
<span class="inbox-item-date">Erledigt: <?= date('d.m.Y, H:i', strtotime($msg['processed_at'])) ?> Uhr</span>
|
||||
</div>
|
||||
<div class="inbox-item-subject"><?= htmlspecialchars($msg['subject'] ?? '') ?></div>
|
||||
<div class="inbox-item-sender">
|
||||
Von: <?= htmlspecialchars($msg['sender_name'] ?? 'Unbekannt') ?>
|
||||
(<?= htmlspecialchars($msg['sender_email'] ?? '') ?>)
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div><!-- inbox-shell -->
|
||||
</div><!-- content -->
|
||||
|
||||
<!-- Registrierungs-Modal -->
|
||||
<div class="standard_overlay" id="registrationModal" onclick="if(event.target.id==='registrationModal')closeRegistrationModal()">
|
||||
<div style="position:relative;width:min(560px,calc(100vw - 24px));max-height:min(700px,calc(100vh - 24px));overflow:auto;background:#FFF;box-shadow:0 24px 70px rgba(0,0,0,0.36);">
|
||||
<button type="button" aria-label="Schließen" onclick="closeRegistrationModal()" style="position:absolute;top:14px;right:14px;width:34px;height:34px;border:1px solid rgba(255,255,255,0.25);background:rgba(255,255,255,0.16);color:#FFF;font-size:1.35em;cursor:pointer;z-index:1;">×</button>
|
||||
|
||||
<div style="padding:24px;color:#FFF;background:radial-gradient(circle at 10% 0%,rgba(255,255,255,0.24),transparent 32%),linear-gradient(135deg,var(--gray-800),var(--gray-900));">
|
||||
<div style="font-size:1.3em;font-weight:850;">Registrierung bearbeiten</div>
|
||||
<div id="regModalUserInfo" style="margin-top:6px;color:rgba(255,255,255,0.8);font-weight:600;"></div>
|
||||
</div>
|
||||
|
||||
<div style="padding:22px 24px 24px 24px;">
|
||||
<form method="post" action="approve-registration.php" id="regModalForm">
|
||||
<input type="hidden" name="pending_id" id="regModalPendingId">
|
||||
<input type="hidden" name="message_id" id="regModalMessageId">
|
||||
<input type="hidden" name="action" id="regModalAction">
|
||||
|
||||
<div style="margin-bottom:16px;">
|
||||
<label style="display:block;margin-bottom:8px;font-weight:750;font-size:0.92em;color:hsl(210,18%,36%);">Rollen zuweisen:</label>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:8px;">
|
||||
<?php foreach ($permissionRoles as $role): ?>
|
||||
<label style="display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid hsl(210,18%,84%);background:hsl(210,12%,98%);cursor:pointer;font-weight:650;font-size:0.88em;hyphens:auto;-webkit-hyphens:auto;overflow-wrap:break-word;">
|
||||
<input type="checkbox" name="roles[]" value="<?= htmlspecialchars($role) ?>" style="accent-color:hsl(210,57%,45%);flex-shrink:0;min-width:16px;min-height:16px;">
|
||||
<?= htmlspecialchars(genderRole($role)) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:20px;">
|
||||
<button type="button" onclick="submitRegistrationAction('reject')" class="inbox-btn inbox-btn-reject" style="padding:10px 18px;font-size:0.9em;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="vertical-align:middle;margin-right:4px;"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>Ablehnen</button>
|
||||
<button type="button" onclick="submitRegistrationAction('approve')" class="inbox-btn inbox-btn-approve" style="padding:10px 18px;font-size:0.9em;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="vertical-align:middle;margin-right:4px;"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>Freischalten</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openRegistrationModal(pendingId, messageId, name, email) {
|
||||
document.getElementById('regModalPendingId').value = pendingId;
|
||||
document.getElementById('regModalMessageId').value = messageId;
|
||||
document.getElementById('regModalUserInfo').textContent = name + ' (' + email + ')';
|
||||
document.getElementById('registrationModal').style.display = 'flex';
|
||||
}
|
||||
function closeRegistrationModal() {
|
||||
document.getElementById('registrationModal').style.display = 'none';
|
||||
}
|
||||
function submitRegistrationAction(action) {
|
||||
var confirmMsg = action === 'approve' ? 'Nutzer mit den gewählten Rollen freischalten?' : 'Registrierung ablehnen?';
|
||||
if (!confirm(confirmMsg)) return;
|
||||
document.getElementById('regModalAction').value = action;
|
||||
document.getElementById('regModalForm').submit();
|
||||
}
|
||||
|
||||
// Brandschutz Eskalation Modal
|
||||
function openBsEscalationModal(msgId, userId, userName, daysOverdue) {
|
||||
document.getElementById('bsEscMsgId').value = msgId;
|
||||
document.getElementById('bsEscUserId').value = userId;
|
||||
document.getElementById('bsEscUserName').textContent = userName;
|
||||
document.getElementById('bsEscDaysOverdue').textContent = daysOverdue + ' Tage';
|
||||
document.getElementById('bsEscalationModal').style.display = 'flex';
|
||||
}
|
||||
function closeBsEscalationModal() {
|
||||
document.getElementById('bsEscalationModal').style.display = 'none';
|
||||
}
|
||||
function submitBsEscalation() {
|
||||
document.getElementById('bsEscForm').submit();
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
if (document.getElementById('registrationModal').style.display === 'flex') {
|
||||
closeRegistrationModal();
|
||||
}
|
||||
if (document.getElementById('bsEscalationModal').style.display === 'flex') {
|
||||
closeBsEscalationModal();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Brandschutz Eskalation Modal -->
|
||||
<div class="standard_overlay" id="bsEscalationModal" onclick="if(event.target.id==='bsEscalationModal')closeBsEscalationModal()">
|
||||
<div style="position:relative;width:min(520px,calc(100vw - 24px));max-height:min(500px,calc(100vh - 24px));overflow:auto;background:#FFF;box-shadow:0 24px 70px rgba(0,0,0,0.36);">
|
||||
<button type="button" aria-label="Schließen" onclick="closeBsEscalationModal()" style="position:absolute;top:14px;right:14px;width:34px;height:34px;border:1px solid rgba(255,255,255,0.25);background:rgba(255,255,255,0.16);color:#FFF;font-size:1.35em;cursor:pointer;z-index:1;">×</button>
|
||||
|
||||
<div style="padding:24px;color:#FFF;background:radial-gradient(circle at 10% 0%,rgba(255,255,255,0.24),transparent 32%),linear-gradient(135deg,hsl(25,90%,45%),hsl(25,95%,35%));">
|
||||
<div style="font-size:1.3em;font-weight:850;">Persönliche Erinnerung bestätigen</div>
|
||||
<div style="margin-top:6px;color:rgba(255,255,255,0.8);font-weight:600;">Brandschutzunterweisung – Eskalation</div>
|
||||
</div>
|
||||
|
||||
<div style="padding:22px 24px 24px 24px;">
|
||||
<p style="margin:0 0 14px 0;font-size:0.95em;color:hsl(210,20%,25%);line-height:1.6;">
|
||||
Bitte bestätigen Sie, dass Sie <strong id="bsEscUserName"></strong> persönlich an die ausstehende Brandschutzunterweisung erinnert haben.
|
||||
</p>
|
||||
<div style="padding:12px 14px;background:hsl(0,65%,95%);border:1px solid hsl(0,65%,85%);margin-bottom:18px;">
|
||||
<div style="font-size:0.78em;font-weight:850;text-transform:uppercase;letter-spacing:0.04em;color:hsl(0,65%,38%);margin-bottom:4px;">Überfälligkeit</div>
|
||||
<div style="font-size:1.1em;font-weight:850;color:hsl(0,65%,35%);" id="bsEscDaysOverdue"></div>
|
||||
</div>
|
||||
|
||||
<form method="post" action="" id="bsEscForm">
|
||||
<input type="hidden" name="bs_escalation_msg_id" id="bsEscMsgId">
|
||||
<input type="hidden" name="bs_escalation_user_id" id="bsEscUserId">
|
||||
<input type="hidden" name="bs_escalation_confirm" value="1">
|
||||
|
||||
<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:16px;">
|
||||
<button type="button" onclick="closeBsEscalationModal()" class="inbox-btn" style="padding:10px 18px;font-size:0.9em;">Abbrechen</button>
|
||||
<button type="submit" class="inbox-btn inbox-btn-approve" style="padding:10px 18px;font-size:0.9em;background:linear-gradient(135deg,var(--nak-orange),hsl(25,95%,40%)) !important;border-color:hsl(25,95%,40%) !important;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="vertical-align:middle;margin-right:4px;"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
|
||||
Bestätigen
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,471 @@
|
||||
<?php
|
||||
/* Name: admin_notices.php
|
||||
Beschreibung: Verwaltung der Meldungen auf dem Intranet-Hauptmenü */
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
|
||||
// Admin-Check
|
||||
$stmt = $pdo->prepare('SELECT "Admin" FROM user_permissions WHERE user_id = ?');
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$isAdmin = $stmt->fetchColumn();
|
||||
|
||||
if ((int)$isAdmin !== 1) {
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit();
|
||||
}
|
||||
|
||||
const NOTICE_MAX_TITLE_LENGTH = 180;
|
||||
const NOTICE_MAX_MESSAGE_LENGTH = 4000;
|
||||
|
||||
$noticeTypes = [
|
||||
'info' => 'Information',
|
||||
'warning' => 'Warnung',
|
||||
'success' => 'Erfolg',
|
||||
'error' => 'Wichtig',
|
||||
];
|
||||
|
||||
if (empty($_SESSION['admin_notices_csrf'])) {
|
||||
$_SESSION['admin_notices_csrf'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$csrfToken = $_SESSION['admin_notices_csrf'];
|
||||
|
||||
function noticeRedirect(string $status): void {
|
||||
header('Location: admin_notices.php?status=' . rawurlencode($status));
|
||||
exit();
|
||||
}
|
||||
|
||||
function noticeVerifyCsrf(): void {
|
||||
$postedToken = $_POST['csrf_token'] ?? '';
|
||||
$sessionToken = $_SESSION['admin_notices_csrf'] ?? '';
|
||||
if (!is_string($postedToken) || !is_string($sessionToken) || $sessionToken === '' || !hash_equals($sessionToken, $postedToken)) {
|
||||
http_response_code(400);
|
||||
exit('Ungültige Anfrage. Bitte laden Sie die Seite neu.');
|
||||
}
|
||||
}
|
||||
|
||||
function noticeParseLocalDateTime(?string $value): ?string {
|
||||
$value = trim((string)$value);
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$tz = new DateTimeZone('Europe/Berlin');
|
||||
$date = DateTimeImmutable::createFromFormat('!Y-m-d\TH:i', $value, $tz);
|
||||
$errors = DateTimeImmutable::getLastErrors();
|
||||
|
||||
if (!$date || ($errors !== false && ($errors['warning_count'] > 0 || $errors['error_count'] > 0))) {
|
||||
throw new InvalidArgumentException('Ungültiges Datum.');
|
||||
}
|
||||
|
||||
// Mit explizitem Offset an PostgreSQL senden, damit TIMESTAMPTZ eindeutig ist.
|
||||
return $date->format('Y-m-d H:i:sP');
|
||||
}
|
||||
|
||||
function noticeFormatLocalDateTime(?string $value): string {
|
||||
if (empty($value)) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
return (new DateTimeImmutable($value))->setTimezone(new DateTimeZone('Europe/Berlin'))->format('Y-m-d\TH:i');
|
||||
} catch (Throwable $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function noticeDisplayDate(?string $value): string {
|
||||
if (empty($value)) {
|
||||
return 'unbegrenzt';
|
||||
}
|
||||
try {
|
||||
return (new DateTimeImmutable($value))->setTimezone(new DateTimeZone('Europe/Berlin'))->format('d.m.Y, H:i') . ' Uhr';
|
||||
} catch (Throwable $e) {
|
||||
return '–';
|
||||
}
|
||||
}
|
||||
|
||||
function noticeDbBool($value): bool {
|
||||
return $value === true || $value === 1 || $value === '1' || $value === 't' || $value === 'true';
|
||||
}
|
||||
|
||||
function noticeTextLength(string $value): int {
|
||||
return function_exists('mb_strlen') ? mb_strlen($value, 'UTF-8') : strlen($value);
|
||||
}
|
||||
|
||||
function noticeValidateInput(array $noticeTypes): array {
|
||||
$title = trim((string)($_POST['title'] ?? ''));
|
||||
$message = trim((string)($_POST['message'] ?? ''));
|
||||
$type = (string)($_POST['type'] ?? 'info');
|
||||
$sortOrder = filter_var($_POST['sort_order'] ?? 0, FILTER_VALIDATE_INT);
|
||||
$isActive = isset($_POST['is_active']);
|
||||
|
||||
if ($title === '' || noticeTextLength($title) > NOTICE_MAX_TITLE_LENGTH) {
|
||||
throw new InvalidArgumentException('Titel fehlt oder ist zu lang.');
|
||||
}
|
||||
if ($message === '' || noticeTextLength($message) > NOTICE_MAX_MESSAGE_LENGTH) {
|
||||
throw new InvalidArgumentException('Meldung fehlt oder ist zu lang.');
|
||||
}
|
||||
if (!array_key_exists($type, $noticeTypes)) {
|
||||
throw new InvalidArgumentException('Ungültiger Meldungstyp.');
|
||||
}
|
||||
if ($sortOrder === false || $sortOrder < -9999 || $sortOrder > 9999) {
|
||||
throw new InvalidArgumentException('Ungültige Sortierung.');
|
||||
}
|
||||
|
||||
$startsAt = noticeParseLocalDateTime($_POST['starts_at'] ?? null);
|
||||
$endsAt = noticeParseLocalDateTime($_POST['ends_at'] ?? null);
|
||||
|
||||
if ($startsAt !== null && $endsAt !== null) {
|
||||
$start = new DateTimeImmutable($startsAt);
|
||||
$end = new DateTimeImmutable($endsAt);
|
||||
if ($end <= $start) {
|
||||
throw new InvalidArgumentException('Das Ende muss nach dem Beginn liegen.');
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $title,
|
||||
'message' => $message,
|
||||
'type' => $type,
|
||||
'sort_order' => (int)$sortOrder,
|
||||
'is_active' => $isActive,
|
||||
'starts_at' => $startsAt,
|
||||
'ends_at' => $endsAt,
|
||||
];
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
noticeVerifyCsrf();
|
||||
$action = (string)($_POST['action'] ?? '');
|
||||
|
||||
try {
|
||||
if ($action === 'create') {
|
||||
$data = noticeValidateInput($noticeTypes);
|
||||
$stmt = $pdo->prepare(
|
||||
'INSERT INTO mainpage_notices
|
||||
(title, message, type, is_active, starts_at, ends_at, sort_order, created_by, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())'
|
||||
);
|
||||
$stmt->execute([
|
||||
$data['title'], $data['message'], $data['type'], $data['is_active'] ? 'true' : 'false',
|
||||
$data['starts_at'], $data['ends_at'], $data['sort_order'], (int)$_SESSION['user_id'],
|
||||
]);
|
||||
noticeRedirect('created');
|
||||
}
|
||||
|
||||
if ($action === 'update') {
|
||||
$id = filter_var($_POST['id'] ?? null, FILTER_VALIDATE_INT);
|
||||
if (!$id || $id < 1) {
|
||||
throw new InvalidArgumentException('Ungültige Meldungs-ID.');
|
||||
}
|
||||
$data = noticeValidateInput($noticeTypes);
|
||||
$stmt = $pdo->prepare(
|
||||
'UPDATE mainpage_notices
|
||||
SET title = ?, message = ?, type = ?, is_active = ?, starts_at = ?, ends_at = ?, sort_order = ?, updated_at = NOW()
|
||||
WHERE id = ?'
|
||||
);
|
||||
$stmt->execute([
|
||||
$data['title'], $data['message'], $data['type'], $data['is_active'] ? 'true' : 'false',
|
||||
$data['starts_at'], $data['ends_at'], $data['sort_order'], (int)$id,
|
||||
]);
|
||||
noticeRedirect('updated');
|
||||
}
|
||||
|
||||
if ($action === 'toggle') {
|
||||
$id = filter_var($_POST['id'] ?? null, FILTER_VALIDATE_INT);
|
||||
if (!$id || $id < 1) {
|
||||
throw new InvalidArgumentException('Ungültige Meldungs-ID.');
|
||||
}
|
||||
$stmt = $pdo->prepare('UPDATE mainpage_notices SET is_active = NOT is_active, updated_at = NOW() WHERE id = ?');
|
||||
$stmt->execute([(int)$id]);
|
||||
noticeRedirect('toggled');
|
||||
}
|
||||
|
||||
if ($action === 'delete') {
|
||||
$id = filter_var($_POST['id'] ?? null, FILTER_VALIDATE_INT);
|
||||
if (!$id || $id < 1) {
|
||||
throw new InvalidArgumentException('Ungültige Meldungs-ID.');
|
||||
}
|
||||
$stmt = $pdo->prepare('DELETE FROM mainpage_notices WHERE id = ?');
|
||||
$stmt->execute([(int)$id]);
|
||||
noticeRedirect('deleted');
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Unbekannte Aktion.');
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$_SESSION['admin_notices_error'] = $e->getMessage();
|
||||
noticeRedirect('error');
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['admin_notices_error'] = 'Datenbankfehler. Prüfen Sie, ob die Tabelle mainpage_notices angelegt wurde.';
|
||||
noticeRedirect('error');
|
||||
}
|
||||
}
|
||||
|
||||
$noticeError = $_SESSION['admin_notices_error'] ?? '';
|
||||
unset($_SESSION['admin_notices_error']);
|
||||
$status = (string)($_GET['status'] ?? '');
|
||||
$statusMessages = [
|
||||
'created' => 'Meldung wurde angelegt.',
|
||||
'updated' => 'Meldung wurde gespeichert.',
|
||||
'toggled' => 'Status der Meldung wurde geändert.',
|
||||
'deleted' => 'Meldung wurde gelöscht.',
|
||||
];
|
||||
|
||||
$tableAvailable = true;
|
||||
$notices = [];
|
||||
try {
|
||||
$notices = $pdo->query(
|
||||
'SELECT id, title, message, type, is_active, starts_at, ends_at, sort_order, created_at, updated_at
|
||||
FROM mainpage_notices
|
||||
ORDER BY sort_order ASC, created_at DESC, id DESC'
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (PDOException $e) {
|
||||
$tableAvailable = false;
|
||||
$noticeError = 'Die Tabelle mainpage_notices fehlt. Führen Sie zuerst general_files/ini/mainpage_notices.sql aus.';
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
<style>
|
||||
.notice-admin-shell { padding: 18px; min-height: 100%; }
|
||||
.notice-admin-card { background:#fff; border:1px solid var(--gray-200); box-shadow:var(--shadow-md); margin-bottom:18px; }
|
||||
.notice-admin-header { display:flex; align-items:center; justify-content:space-between; gap:16px; padding:16px 18px; border-bottom:1px solid var(--gray-200); }
|
||||
.notice-admin-title { font-size:1.05em; font-weight:800; color:var(--gray-900); }
|
||||
.notice-admin-hint { margin-top:3px; font-size:.86em; color:var(--gray-500); }
|
||||
.notice-admin-button { display:inline-flex; align-items:center; justify-content:center; min-height:36px; padding:7px 14px; border:1px solid var(--gray-800); background:var(--gray-900); color:#fff; font:inherit; font-size:.86em; font-weight:750; cursor:pointer; text-decoration:none; }
|
||||
.notice-admin-button:hover { color:#fff; background:#111; text-decoration:none; }
|
||||
.notice-admin-button--secondary { color:var(--gray-800); background:#fff; border-color:var(--gray-300); }
|
||||
.notice-admin-button--secondary:hover { color:var(--gray-900); background:var(--gray-50); }
|
||||
.notice-admin-button--danger { color:var(--nak-red); background:#fff; border-color:hsl(352,72%,84%); }
|
||||
.notice-admin-button--danger:hover { color:#fff; background:var(--nak-red); }
|
||||
.notice-admin-grid { display:grid; gap:12px; padding:16px 18px 18px; }
|
||||
.notice-admin-item { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:16px; padding:16px; border:1px solid var(--gray-200); background:var(--gray-50); }
|
||||
.notice-admin-item.is-disabled { opacity:.62; }
|
||||
.notice-admin-item-title { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:6px; font-weight:800; color:var(--gray-900); }
|
||||
.notice-admin-chip { display:inline-flex; align-items:center; padding:3px 8px; font-size:.72em; font-weight:800; border-left:3px solid currentColor; background:#fff; }
|
||||
.notice-admin-chip--info { color:var(--nak-blue); }
|
||||
.notice-admin-chip--warning { color:var(--nak-orange); }
|
||||
.notice-admin-chip--success { color:var(--nak-darkgreen); }
|
||||
.notice-admin-chip--error { color:var(--nak-red); }
|
||||
.notice-admin-message { white-space:pre-wrap; line-height:1.45; color:var(--gray-700); font-size:.92em; }
|
||||
.notice-admin-meta { display:flex; gap:14px; flex-wrap:wrap; margin-top:10px; color:var(--gray-500); font-size:.8em; }
|
||||
.notice-admin-actions { display:flex; align-items:flex-start; gap:7px; flex-wrap:wrap; justify-content:flex-end; }
|
||||
.notice-admin-actions form { margin:0; }
|
||||
.notice-admin-empty { padding:28px 18px; text-align:center; color:var(--gray-500); }
|
||||
.notice-admin-alert { margin:16px 18px 0; padding:11px 13px; border-left:4px solid var(--nak-darkgreen); background:hsl(145,50%,94%); color:hsl(145,50%,28%); font-size:.9em; }
|
||||
.notice-admin-alert--error { border-color:var(--nak-red); background:hsl(352,72%,96%); color:hsl(352,62%,35%); }
|
||||
|
||||
.notice-modal { position:fixed; inset:0; z-index:5000; display:none; align-items:center; justify-content:center; padding:20px; background:rgba(16,24,32,.62); }
|
||||
.notice-modal.open { display:flex; }
|
||||
.notice-modal-card { width:min(680px,100%); max-height:calc(100dvh - 40px); overflow:auto; background:#fff; box-shadow:var(--shadow-xl); }
|
||||
.notice-modal-header { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:18px 20px; border-bottom:1px solid var(--gray-200); }
|
||||
.notice-modal-title { font-size:1.08em; font-weight:800; color:var(--gray-900); }
|
||||
.notice-modal-close { border:0; background:transparent; font-size:1.5em; line-height:1; cursor:pointer; color:var(--gray-500); }
|
||||
.notice-modal-body { padding:20px; }
|
||||
.notice-form-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
|
||||
.notice-field { display:flex; flex-direction:column; gap:6px; }
|
||||
.notice-field--full { grid-column:1 / -1; }
|
||||
.notice-field label { font-size:.83em; font-weight:750; color:var(--gray-700); }
|
||||
.notice-field input, .notice-field select, .notice-field textarea { width:100%; box-sizing:border-box; padding:10px 11px; border:1px solid var(--gray-300); background:#fff; color:var(--gray-900); font:inherit; font-size:.9em; }
|
||||
.notice-field textarea { min-height:120px; resize:vertical; }
|
||||
.notice-checkbox { display:flex; align-items:center; gap:8px; min-height:40px; }
|
||||
.notice-checkbox input { width:auto; }
|
||||
.notice-form-note { margin-top:5px; font-size:.78em; color:var(--gray-500); }
|
||||
.notice-modal-actions { display:flex; justify-content:flex-end; gap:8px; padding:0 20px 20px; }
|
||||
|
||||
@media (max-width:760px) {
|
||||
.notice-admin-shell { padding:10px; }
|
||||
.notice-admin-header, .notice-admin-item { grid-template-columns:1fr; display:grid; }
|
||||
.notice-admin-actions { justify-content:flex-start; }
|
||||
.notice-form-grid { grid-template-columns:1fr; }
|
||||
.notice-field--full { grid-column:auto; }
|
||||
.content-tab-bar { overflow-x:auto; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="theme-admin">
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
|
||||
<?php include $g_phpSnippetsPath.'overlay_message.php'; ?>
|
||||
|
||||
<div class="header_title ht_admin text_white unselectable" id="header_title">
|
||||
<span class="header_title_text">Adminpanel</span>
|
||||
</div>
|
||||
|
||||
<div class="content" id="fullsize">
|
||||
<?php $adminActiveTab = 'notices'; require __DIR__.'/_tabs.php'; ?>
|
||||
|
||||
<div class="notice-admin-shell">
|
||||
<div class="notice-admin-card">
|
||||
<div class="notice-admin-header">
|
||||
<div>
|
||||
<div class="notice-admin-title">Meldungen im Hauptmenü</div>
|
||||
<div class="notice-admin-hint">Meldungen erscheinen ausschließlich oberhalb der Kacheln auf der Intranet-Hauptseite.</div>
|
||||
</div>
|
||||
<?php if ($tableAvailable): ?>
|
||||
<button type="button" class="notice-admin-button" onclick="openNoticeModal()">+ Neue Meldung</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($status === 'error' && $noticeError !== ''): ?>
|
||||
<div class="notice-admin-alert notice-admin-alert--error"><?= htmlspecialchars($noticeError, ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<?php elseif (!$tableAvailable && $noticeError !== ''): ?>
|
||||
<div class="notice-admin-alert notice-admin-alert--error"><?= htmlspecialchars($noticeError, ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<?php elseif (isset($statusMessages[$status])): ?>
|
||||
<div class="notice-admin-alert"><?= htmlspecialchars($statusMessages[$status], ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($tableAvailable): ?>
|
||||
<?php if (empty($notices)): ?>
|
||||
<div class="notice-admin-empty">Noch keine Meldungen vorhanden.</div>
|
||||
<?php else: ?>
|
||||
<div class="notice-admin-grid">
|
||||
<?php foreach ($notices as $notice): ?>
|
||||
<?php
|
||||
$noticeId = (int)$notice['id'];
|
||||
$noticeType = array_key_exists($notice['type'], $noticeTypes) ? $notice['type'] : 'info';
|
||||
$editPayload = [
|
||||
'id' => $noticeId,
|
||||
'title' => $notice['title'],
|
||||
'message' => $notice['message'],
|
||||
'type' => $noticeType,
|
||||
'is_active' => noticeDbBool($notice['is_active']),
|
||||
'starts_at' => noticeFormatLocalDateTime($notice['starts_at']),
|
||||
'ends_at' => noticeFormatLocalDateTime($notice['ends_at']),
|
||||
'sort_order' => (int)$notice['sort_order'],
|
||||
];
|
||||
?>
|
||||
<div class="notice-admin-item<?= noticeDbBool($notice['is_active']) ? '' : ' is-disabled' ?>">
|
||||
<div>
|
||||
<div class="notice-admin-item-title">
|
||||
<?= htmlspecialchars($notice['title'], ENT_QUOTES, 'UTF-8') ?>
|
||||
<span class="notice-admin-chip notice-admin-chip--<?= htmlspecialchars($noticeType, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($noticeTypes[$noticeType], ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<?php if (!noticeDbBool($notice['is_active'])): ?><span class="notice-admin-chip">Deaktiviert</span><?php endif; ?>
|
||||
</div>
|
||||
<div class="notice-admin-message"><?= htmlspecialchars($notice['message'], ENT_QUOTES, 'UTF-8') ?></div>
|
||||
<div class="notice-admin-meta">
|
||||
<span>Von: <?= htmlspecialchars(noticeDisplayDate($notice['starts_at']), ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span>Bis: <?= htmlspecialchars(noticeDisplayDate($notice['ends_at']), ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span>Sortierung: <?= (int)$notice['sort_order'] ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="notice-admin-actions">
|
||||
<button type="button" class="notice-admin-button notice-admin-button--secondary" onclick='openNoticeModal(<?= json_encode($editPayload, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) ?>)'>Bearbeiten</button>
|
||||
<form method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<input type="hidden" name="action" value="toggle">
|
||||
<input type="hidden" name="id" value="<?= $noticeId ?>">
|
||||
<button type="submit" class="notice-admin-button notice-admin-button--secondary"><?= noticeDbBool($notice['is_active']) ? 'Deaktivieren' : 'Aktivieren' ?></button>
|
||||
</form>
|
||||
<form method="post" onsubmit="return confirm('Meldung wirklich dauerhaft löschen?');">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="id" value="<?= $noticeId ?>">
|
||||
<button type="submit" class="notice-admin-button notice-admin-button--danger">Löschen</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="notice-modal" id="noticeModal" aria-hidden="true">
|
||||
<div class="notice-modal-card" role="dialog" aria-modal="true" aria-labelledby="noticeModalTitle">
|
||||
<form method="post" id="noticeForm">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<input type="hidden" name="action" id="noticeAction" value="create">
|
||||
<input type="hidden" name="id" id="noticeId" value="">
|
||||
|
||||
<div class="notice-modal-header">
|
||||
<div class="notice-modal-title" id="noticeModalTitle">Neue Meldung</div>
|
||||
<button type="button" class="notice-modal-close" onclick="closeNoticeModal()" aria-label="Schließen">×</button>
|
||||
</div>
|
||||
<div class="notice-modal-body">
|
||||
<div class="notice-form-grid">
|
||||
<div class="notice-field notice-field--full">
|
||||
<label for="noticeTitle">Titel</label>
|
||||
<input id="noticeTitle" name="title" type="text" maxlength="180" required>
|
||||
</div>
|
||||
<div class="notice-field notice-field--full">
|
||||
<label for="noticeMessage">Meldung</label>
|
||||
<textarea id="noticeMessage" name="message" maxlength="4000" required></textarea>
|
||||
</div>
|
||||
<div class="notice-field">
|
||||
<label for="noticeType">Typ</label>
|
||||
<select id="noticeType" name="type">
|
||||
<?php foreach ($noticeTypes as $typeKey => $typeLabel): ?>
|
||||
<option value="<?= htmlspecialchars($typeKey, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($typeLabel, ENT_QUOTES, 'UTF-8') ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="notice-field">
|
||||
<label for="noticeSortOrder">Sortierung</label>
|
||||
<input id="noticeSortOrder" name="sort_order" type="number" min="-9999" max="9999" value="0" required>
|
||||
<div class="notice-form-note">Kleinere Zahlen erscheinen zuerst.</div>
|
||||
</div>
|
||||
<div class="notice-field">
|
||||
<label for="noticeStartsAt">Anzeigen ab</label>
|
||||
<input id="noticeStartsAt" name="starts_at" type="datetime-local">
|
||||
<div class="notice-form-note">Leer = sofort.</div>
|
||||
</div>
|
||||
<div class="notice-field">
|
||||
<label for="noticeEndsAt">Anzeigen bis</label>
|
||||
<input id="noticeEndsAt" name="ends_at" type="datetime-local">
|
||||
<div class="notice-form-note">Leer = ohne Ablaufdatum.</div>
|
||||
</div>
|
||||
<div class="notice-field notice-field--full">
|
||||
<label class="notice-checkbox">
|
||||
<input id="noticeIsActive" name="is_active" type="checkbox" value="1" checked>
|
||||
Meldung aktiv
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="notice-modal-actions">
|
||||
<button type="button" class="notice-admin-button notice-admin-button--secondary" onclick="closeNoticeModal()">Abbrechen</button>
|
||||
<button type="submit" class="notice-admin-button">Speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openNoticeModal(data) {
|
||||
data = data || null;
|
||||
var modal = document.getElementById('noticeModal');
|
||||
document.getElementById('noticeAction').value = data ? 'update' : 'create';
|
||||
document.getElementById('noticeId').value = data ? data.id : '';
|
||||
document.getElementById('noticeTitle').value = data ? data.title : '';
|
||||
document.getElementById('noticeMessage').value = data ? data.message : '';
|
||||
document.getElementById('noticeType').value = data ? data.type : 'warning';
|
||||
document.getElementById('noticeSortOrder').value = data ? data.sort_order : 0;
|
||||
document.getElementById('noticeStartsAt').value = data ? data.starts_at : '';
|
||||
document.getElementById('noticeEndsAt').value = data ? data.ends_at : '';
|
||||
document.getElementById('noticeIsActive').checked = data ? !!data.is_active : true;
|
||||
document.getElementById('noticeModalTitle').textContent = data ? 'Meldung bearbeiten' : 'Neue Meldung';
|
||||
modal.classList.add('open');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
document.getElementById('noticeTitle').focus();
|
||||
}
|
||||
|
||||
function closeNoticeModal() {
|
||||
var modal = document.getElementById('noticeModal');
|
||||
modal.classList.remove('open');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
document.getElementById('noticeModal').addEventListener('click', function(event) {
|
||||
if (event.target === this) closeNoticeModal();
|
||||
});
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Escape') closeNoticeModal();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php /* Name: admin_profiles.php
|
||||
Beschreibung: Administratoren-Seite zur Nutzerverwaltung */
|
||||
|
||||
// Initialisierung
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
</head>
|
||||
<body class="theme-admin">
|
||||
|
||||
<?php /* Besondere Admin-Rechte checken */
|
||||
// Fetch user details
|
||||
$stmt = $pdo->prepare("SELECT * FROM user_permissions up INNER JOIN user_general_information ugi ON up.user_id = ugi.user_id WHERE up.user_id = ?");
|
||||
$stmt->execute([$_SESSION["user_id"]]);
|
||||
$isAdmin = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// Check if the user has admin access (Admin = 1)
|
||||
if ($isAdmin["Admin"] == 1) {
|
||||
$sql_groups = "SELECT * FROM user_permissions";
|
||||
$stmt = $pdo->prepare($sql_groups);
|
||||
$stmt->execute([]);
|
||||
$groups = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
} else {
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
|
||||
<?php // Es folgen ab hier die HTML-Ausgaben beginnend mit dem HTML-Header: ?>
|
||||
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
|
||||
|
||||
|
||||
<?php // Header (einfach): Titel der Seite ?>
|
||||
<div class="header_title ht_admin text_white" id="header_title">
|
||||
<div class="flexrow fullwidth" style="justify-content:space-between !important;">
|
||||
<div class="header_title_text">Nutzerverwaltung</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php // Profilanzeige
|
||||
require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/projects/intranet/show_profile.php"); ?>
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php /* Name: approve-registration.php
|
||||
Beschreibung: Admin genehmigt oder lehnt eine Registrierungsanfrage ab.
|
||||
- Setzt Rollen bei Freischaltung
|
||||
- Sendet Mails an Nutzer UND Admins
|
||||
POST-Parameter: action (approve/reject), pending_id, message_id, roles[] */
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/send_mail.php';
|
||||
|
||||
// Admin-Check
|
||||
$stmt = $pdo->prepare("SELECT \"Admin\" FROM user_permissions WHERE user_id = ?");
|
||||
$stmt->execute([$_SESSION["user_id"]]);
|
||||
$isAdmin = $stmt->fetchColumn();
|
||||
|
||||
if ((int)$isAdmin !== 1) {
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||
header("Location: admin_inbox.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Admin-Name ermitteln
|
||||
$adminName = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
|
||||
if (empty($adminName)) $adminName = 'Ein Administrator';
|
||||
|
||||
$action = $_POST["action"] ?? '';
|
||||
$pending_id = (int)($_POST["pending_id"] ?? 0);
|
||||
$message_id = (int)($_POST["message_id"] ?? 0);
|
||||
$selectedRoles = $_POST["roles"] ?? [];
|
||||
if (!is_array($selectedRoles)) $selectedRoles = [];
|
||||
|
||||
if ($pending_id === 0) {
|
||||
header("Location: admin_inbox.php?inbox_status=error");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Pending Registration laden
|
||||
$stmt = $pdo->prepare("SELECT * FROM pending_registrations WHERE id = ? AND status = 'pending'");
|
||||
$stmt->execute([$pending_id]);
|
||||
$pending = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$pending) {
|
||||
header("Location: admin_inbox.php?inbox_status=error");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Rollen-Spalten laden
|
||||
$permissionRoles = [];
|
||||
$rolesResult = $pdo->query("SELECT column_name FROM information_schema.columns WHERE table_name = 'user_permissions' AND table_schema = 'public'");
|
||||
while ($col = $rolesResult->fetch(PDO::FETCH_ASSOC)) {
|
||||
if (!in_array($col['column_name'], ['p_id', 'user_id'], true)) {
|
||||
$permissionRoles[] = $col['column_name'];
|
||||
}
|
||||
}
|
||||
|
||||
$loginUrl = "https://" . ($_SERVER['HTTP_HOST'] ?? intranet_env('INTRANET_FQDN')) . "/intranet_repo/projects/authorization/login.php";
|
||||
|
||||
if ($action === 'approve') {
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
// Nutzer in user_general_information anlegen
|
||||
$stmt = $pdo->prepare("INSERT INTO user_general_information (mail, first_name, last_name, phone) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$pending['email'], $pending['first_name'], $pending['last_name'], $pending['phone']]);
|
||||
$newUserId = $pdo->lastInsertId();
|
||||
|
||||
if (!$newUserId) {
|
||||
$checkStmt = $pdo->prepare("SELECT user_id FROM user_general_information WHERE mail = ?");
|
||||
$checkStmt->execute([$pending['email']]);
|
||||
$newUserId = $checkStmt->fetchColumn();
|
||||
}
|
||||
|
||||
// Login-Daten anlegen
|
||||
$stmt = $pdo->prepare("INSERT INTO user_login (user_id, password_hash) VALUES (?, ?)");
|
||||
$stmt->execute([$newUserId, $pending['password_hash']]);
|
||||
|
||||
// Berechtigungen mit gewählten Rollen anlegen
|
||||
$roleColumns = array_map(function($r) { return '"' . str_replace('"', '""', $r) . '"'; }, $permissionRoles);
|
||||
$columns = array_merge(['"user_id"'], $roleColumns);
|
||||
$placeholders = array_fill(0, count($columns), '?');
|
||||
$roleValues = [];
|
||||
foreach ($permissionRoles as $role) {
|
||||
$roleValues[] = in_array($role, $selectedRoles, true) ? 1 : 0;
|
||||
}
|
||||
$params = array_merge([(int)$newUserId], $roleValues);
|
||||
|
||||
$insertSql = "INSERT INTO user_permissions (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $placeholders) . ")";
|
||||
$stmt = $pdo->prepare($insertSql);
|
||||
$stmt->execute($params);
|
||||
|
||||
// Pending-Status aktualisieren
|
||||
$stmt = $pdo->prepare("UPDATE pending_registrations SET status = 'approved' WHERE id = ?");
|
||||
$stmt->execute([$pending_id]);
|
||||
|
||||
// Inbox-Nachricht als erledigt markieren
|
||||
if ($message_id > 0) {
|
||||
$stmt = $pdo->prepare("UPDATE admin_messages SET status = 'done', processed_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$message_id]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
// Zugewiesene Rollen als Text
|
||||
$assignedRoles = !empty($selectedRoles) ? implode(', ', $selectedRoles) : 'Keine besonderen Rollen';
|
||||
|
||||
// Mail an den Nutzer
|
||||
$userBetreff = "Registrierung freigeschaltet";
|
||||
$userNachricht = "Hallo {$pending['first_name']},\n\n";
|
||||
$userNachricht .= "Ihr Account für das Intranet der NAK Reinickendorf wurde freigeschaltet!\n\n";
|
||||
$userNachricht .= "Sie können sich ab sofort mit Ihrer E-Mail-Adresse und dem von Ihnen gewählten Passwort anmelden.";
|
||||
|
||||
send_intranet_mail($pending['email'], $userBetreff, $userNachricht, null, "intranet@nak-reinickendorf.de", "Jetzt anmelden", $loginUrl);
|
||||
|
||||
// Mail an Admin-Team
|
||||
$adminBetreff = "Registrierung freigegeben: {$pending['first_name']} {$pending['last_name']}";
|
||||
$adminNachricht = "{$adminName} hat die Registrierung bearbeitet:\n\n";
|
||||
$adminNachricht .= "Nutzer: {$pending['first_name']} {$pending['last_name']}\n";
|
||||
$adminNachricht .= "E-Mail: {$pending['email']}\n";
|
||||
$adminNachricht .= "Aktion: Freigeschaltet\n";
|
||||
$adminNachricht .= "Zugewiesene Rollen: {$assignedRoles}";
|
||||
|
||||
send_admin_team_mail($pdo, $adminBetreff, $adminNachricht);
|
||||
|
||||
// Systemnachricht im Posteingang
|
||||
$sysSubject = "Nutzer freigeschaltet: {$pending['first_name']} {$pending['last_name']}";
|
||||
$sysMessage = "{$adminName} hat {$pending['first_name']} {$pending['last_name']} ({$pending['email']}) freigeschaltet.\nZugewiesene Rollen: {$assignedRoles}";
|
||||
$stmtSys = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())");
|
||||
$stmtSys->execute([$adminName, $pending['email'], $sysSubject, $sysMessage]);
|
||||
|
||||
header("Location: admin_inbox.php?inbox_status=approved");
|
||||
exit();
|
||||
|
||||
} catch (Throwable $e) {
|
||||
$pdo->rollBack();
|
||||
error_log("approve-registration error: " . $e->getMessage());
|
||||
header("Location: admin_inbox.php?inbox_status=error");
|
||||
exit();
|
||||
}
|
||||
|
||||
} elseif ($action === 'reject') {
|
||||
// Ablehnen
|
||||
$stmt = $pdo->prepare("UPDATE pending_registrations SET status = 'rejected' WHERE id = ?");
|
||||
$stmt->execute([$pending_id]);
|
||||
|
||||
// Inbox-Nachricht als erledigt markieren
|
||||
if ($message_id > 0) {
|
||||
$stmt = $pdo->prepare("UPDATE admin_messages SET status = 'done', processed_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$message_id]);
|
||||
}
|
||||
|
||||
// Mail an den Nutzer
|
||||
$userBetreff = "Registrierung abgelehnt";
|
||||
$userNachricht = "Hallo {$pending['first_name']},\n\n";
|
||||
$userNachricht .= "Ihre Registrierungsanfrage für das Intranet der NAK Reinickendorf wurde leider abgelehnt.\n\n";
|
||||
$userNachricht .= "Bei Fragen wenden Sie sich bitte an den Administrator über das Kontaktformular auf der Anmeldeseite.";
|
||||
|
||||
send_intranet_mail($pending['email'], $userBetreff, $userNachricht);
|
||||
|
||||
// Mail an Admin-Team
|
||||
$adminBetreff = "Registrierung abgelehnt: {$pending['first_name']} {$pending['last_name']}";
|
||||
$adminNachricht = "{$adminName} hat die Registrierung bearbeitet:\n\n";
|
||||
$adminNachricht .= "Nutzer: {$pending['first_name']} {$pending['last_name']}\n";
|
||||
$adminNachricht .= "E-Mail: {$pending['email']}\n";
|
||||
$adminNachricht .= "Aktion: Abgelehnt";
|
||||
|
||||
send_admin_team_mail($pdo, $adminBetreff, $adminNachricht);
|
||||
|
||||
// Systemnachricht im Posteingang
|
||||
$sysSubject = "Registrierung abgelehnt: {$pending['first_name']} {$pending['last_name']}";
|
||||
$sysMessage = "{$adminName} hat die Registrierung von {$pending['first_name']} {$pending['last_name']} ({$pending['email']}) abgelehnt.";
|
||||
$stmtSys = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())");
|
||||
$stmtSys->execute([$adminName, $pending['email'], $sysSubject, $sysMessage]);
|
||||
|
||||
header("Location: admin_inbox.php?inbox_status=rejected");
|
||||
exit();
|
||||
}
|
||||
|
||||
header("Location: admin_inbox.php");
|
||||
exit();
|
||||
?>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php /* Name: process_contact.php
|
||||
Beschreibung: Verarbeitung von Kontaktformular-Anfragen
|
||||
- Speichert in admin_messages
|
||||
- Sendet Mail an technik@nak-reinickendorf.de */
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$pdo = require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/send_mail.php';
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'error' => 'Methode nicht erlaubt']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Felder auslesen
|
||||
$name = trim($_POST["contact_name"] ?? '');
|
||||
$email = trim($_POST["contact_email"] ?? '');
|
||||
$subject = trim($_POST["contact_subject"] ?? 'Kontaktanfrage');
|
||||
$message = trim($_POST["contact_message"] ?? '');
|
||||
|
||||
// Validierung
|
||||
if (empty($name) || empty($email) || empty($message)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Bitte alle Felder ausfüllen.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'error' => 'Ungültige E-Mail-Adresse.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// In admin_messages speichern
|
||||
$stmt = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message) VALUES ('contact', ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $email, $subject, $message]);
|
||||
|
||||
// Mail an Admin-Team (Admin + Technik)
|
||||
$mail_betreff = "Kontaktanfrage: {$subject}";
|
||||
$mail_nachricht = "Neue Kontaktanfrage über das Intranet:\n\n";
|
||||
$mail_nachricht .= "Name: {$name}\n";
|
||||
$mail_nachricht .= "E-Mail: {$email}\n";
|
||||
$mail_nachricht .= "Betreff: {$subject}\n\n";
|
||||
$mail_nachricht .= "Nachricht:\n{$message}";
|
||||
|
||||
send_admin_team_mail($pdo, $mail_betreff, $mail_nachricht);
|
||||
|
||||
// JSON-Antwort für AJAX
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => true, 'message' => 'Nachricht wurde gesendet.']);
|
||||
exit;
|
||||
?>
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php /* Name: login.php
|
||||
Beschreibung: Login-Seite (Authorisierung) */
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/functions.php';
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
|
||||
$pdo = require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
|
||||
$sql = "SELECT
|
||||
u.*,
|
||||
l.password_hash AS password_hash
|
||||
FROM
|
||||
user_general_information AS u
|
||||
INNER JOIN
|
||||
user_login AS l ON u.user_id = l.user_id
|
||||
WHERE
|
||||
u.mail = ?";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$_POST["email"]]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user) {
|
||||
|
||||
if (isset($user['password_hash']) && password_verify($_POST["password"], $user["password_hash"])) {
|
||||
|
||||
session_start();
|
||||
session_regenerate_id();
|
||||
$_SESSION["user_id"] = $user["user_id"];
|
||||
|
||||
header("Location: {$g_httpHomePath}");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$is_invalid = true;
|
||||
}
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
|
||||
<script src="https://unpkg.com/just-validate@latest/dist/just-validate.production.min.js" defer></script>
|
||||
<script src="validation.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login_panel">
|
||||
|
||||
<?php if (isset($is_invalid) && $is_invalid): ?>
|
||||
<div class="nak-toast nak-toast--error nak-toast--inline" id="nakToastLogin">
|
||||
<div class="nak-toast__icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
|
||||
</div>
|
||||
<span class="nak-toast__text">Ungültiger Login!</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastLogin').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_GET["message"]) && $_GET["message"] == 1): ?>
|
||||
<div class="nak-toast nak-toast--success nak-toast--inline" id="nakToastPw">
|
||||
<div class="nak-toast__icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg>
|
||||
</div>
|
||||
<span class="nak-toast__text">Passwort erfolgreich geändert. Sie können sich jetzt anmelden.</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastPw').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
<div class="login_content">
|
||||
<div class="nak-logo-link auth-logo">
|
||||
<img class="auth-logo__icon" src="/intranet_repo/projects/_central/img/nak-logo.svg" alt="NAK Logo">
|
||||
<div class="auth-logo__text">
|
||||
<div class="auth-logo__name">Neuapostolische Kirche</div>
|
||||
<div class="auth-logo__gemeinde">Berlin-Reinickendorf</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Anmelden</h2>
|
||||
|
||||
<form method="post">
|
||||
<div class="flexcolumn_center">
|
||||
<input class="login_field" placeholder="E-Mailadresse" type="email" name="email" id="email"
|
||||
value="<?= htmlspecialchars($_POST["email"] ?? "") ?>">
|
||||
<input class="login_field" placeholder="Passwort" type="password" name="password" id="password">
|
||||
<input class="login_button" type="submit" name="submit" value="Anmelden">
|
||||
</div>
|
||||
</form>
|
||||
<div class="small_text" style="text-align:center;margin-top:24px;color:var(--gray-600);">
|
||||
Sie haben noch keinen Account für das Intranet?<br>
|
||||
<a href="signup.php">Registrieren</a><br>
|
||||
<br>
|
||||
Passwort vergessen?<br>
|
||||
<a href="reset-password.php">Passwort zurücksetzen</a><br>
|
||||
<br>
|
||||
Probleme bei der Anmeldung?<br>
|
||||
<a href="#" onclick="openContactModal(); return false;">Admin kontaktieren</a>
|
||||
</div>
|
||||
</div><!-- EOD: login_content -->
|
||||
</div><!-- EOD: login_panel -->
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php /* Name: loginout.php
|
||||
Beschreibung: Logout-Seite */
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/functions.php';
|
||||
|
||||
session_destroy();
|
||||
|
||||
header("Location: {$g_httpLoginPath}");
|
||||
exit();
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php /* Name: reset-password-process.php
|
||||
Beschreibung: Verarbeitung des Passwort-Resets (3 Schritte)
|
||||
- Schritt 1: OTP generieren und per SMS + Mail senden
|
||||
- Schritt 2: OTP verifizieren → Reset-Token erzeugen
|
||||
- Schritt 3: Neues Passwort setzen mit Reset-Token */
|
||||
|
||||
$pdo = require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/send_mail.php';
|
||||
|
||||
// PostgreSQL-Zeitzone auf PHP-Zeitzone setzen
|
||||
$pdo->exec("SET timezone = 'Europe/Berlin'");
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||
header("Location: reset-password.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$action = $_POST["action"] ?? '';
|
||||
|
||||
// =============================================
|
||||
// SCHRITT 1: OTP anfordern
|
||||
// =============================================
|
||||
if ($action === "request_otp") {
|
||||
$email = trim($_POST["email"] ?? '');
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
header("Location: reset-password.php?error=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Nutzer suchen (muss registriert sein = user_login existiert)
|
||||
$stmt = $pdo->prepare("SELECT ugi.user_id, ugi.phone, ugi.first_name FROM user_general_information ugi INNER JOIN user_login ul ON ugi.user_id = ul.user_id WHERE ugi.mail = ?");
|
||||
$stmt->execute([$email]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!$user) {
|
||||
header("Location: reset-password.php?error=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (empty($user['phone'])) {
|
||||
header("Location: reset-password.php?error=2");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP generieren (6-stellig)
|
||||
$otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
|
||||
|
||||
// Ablaufzeit als UNIX-Timestamp speichern (vermeidet Timezone-Probleme)
|
||||
$expires_timestamp = time() + 600; // 10 Minuten
|
||||
$expires_at = date('Y-m-d H:i:s', $expires_timestamp);
|
||||
|
||||
// Alte OTPs für diesen Nutzer invalidieren
|
||||
$stmt = $pdo->prepare("UPDATE password_reset_otp SET used = 1 WHERE user_id = ? AND used = 0");
|
||||
$stmt->execute([$user['user_id']]);
|
||||
|
||||
// Neues OTP speichern
|
||||
$stmt = $pdo->prepare("INSERT INTO password_reset_otp (user_id, otp_code, expires_at) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$user['user_id'], $otp, $expires_at]);
|
||||
|
||||
// SMS senden (wie im Seelsorgeplaner)
|
||||
$phone_full = "+49" . $user['phone'];
|
||||
$messageText = "Intranet NAK Reinickendorf\n\nIhr Bestaetigungscode: {$otp}\n\nDer Code ist 10 Minuten gueltig.";
|
||||
|
||||
$smsData = array(
|
||||
"phone" => $phone_full,
|
||||
"message" => $messageText
|
||||
);
|
||||
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => "Content-Type: application/json; charset=utf-8",
|
||||
'method' => 'POST',
|
||||
'content' => json_encode($smsData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'timeout' => 10,
|
||||
),
|
||||
);
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$smsResult = @file_get_contents(rtrim(intranet_env('SMS_GATEWAY_URL'), '/') . '/send_sms', false, $context);
|
||||
|
||||
if ($smsResult === FALSE) {
|
||||
header("Location: reset-password.php?error=4");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP zusätzlich per Mail senden
|
||||
$greeting = !empty($user['first_name']) ? "Hallo {$user['first_name']}" : "Hallo";
|
||||
$mailBetreff = "Ihr Bestätigungscode";
|
||||
$mailNachricht = "{$greeting},\n\n";
|
||||
$mailNachricht .= "Sie haben das Zurücksetzen Ihres Passworts angefordert.\n\n";
|
||||
$mailNachricht .= "Ihr Bestätigungscode lautet: {$otp}\n\n";
|
||||
$mailNachricht .= "Der Code ist 10 Minuten gültig.\n\n";
|
||||
$mailNachricht .= "Falls Sie diese Anfrage nicht gestellt haben, können Sie diese Nachricht ignorieren.";
|
||||
|
||||
send_intranet_mail($email, $mailBetreff, $mailNachricht);
|
||||
|
||||
// Telefonnummer maskieren für Anzeige (nur letzte 3 Ziffern zeigen)
|
||||
$phone_masked = str_repeat('*', max(0, strlen($user['phone']) - 3)) . substr($user['phone'], -3);
|
||||
|
||||
header("Location: reset-password.php?step=verify&uid={$user['user_id']}&phone=" . urlencode($phone_masked));
|
||||
exit;
|
||||
}
|
||||
|
||||
// =============================================
|
||||
// SCHRITT 2: OTP verifizieren → Reset-Token erzeugen
|
||||
// =============================================
|
||||
if ($action === "verify_otp") {
|
||||
$user_id = (int)($_POST["user_id"] ?? 0);
|
||||
$otp_code = trim($_POST["otp_code"] ?? '');
|
||||
|
||||
if ($user_id === 0 || strlen($otp_code) !== 6) {
|
||||
header("Location: reset-password.php?error=3");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP prüfen – Vergleich mit PHP-Zeit statt DB NOW()
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$stmt = $pdo->prepare("SELECT id FROM password_reset_otp WHERE user_id = ? AND otp_code = ? AND used = 0 AND expires_at > ?");
|
||||
$stmt->execute([$user_id, $otp_code, $now]);
|
||||
$otpRecord = $stmt->fetch();
|
||||
|
||||
if (!$otpRecord) {
|
||||
header("Location: reset-password.php?step=verify&uid={$user_id}&error=3");
|
||||
exit;
|
||||
}
|
||||
|
||||
// OTP als verwendet markieren
|
||||
$stmt = $pdo->prepare("UPDATE password_reset_otp SET used = 1 WHERE id = ?");
|
||||
$stmt->execute([$otpRecord['id']]);
|
||||
|
||||
// Einmal-Token für Passwort-Änderung generieren (in Session speichern)
|
||||
$reset_token = bin2hex(random_bytes(32));
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
$_SESSION['reset_token'] = $reset_token;
|
||||
$_SESSION['reset_user_id'] = $user_id;
|
||||
$_SESSION['reset_token_expires'] = time() + 600; // 10 Minuten
|
||||
|
||||
header("Location: reset-password.php?step=newpassword&token=" . urlencode($reset_token));
|
||||
exit;
|
||||
}
|
||||
|
||||
// =============================================
|
||||
// SCHRITT 3: Neues Passwort setzen (nach OTP-Verifizierung)
|
||||
// =============================================
|
||||
if ($action === "set_password") {
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$reset_token = $_POST["reset_token"] ?? '';
|
||||
$new_password = $_POST["new_password"] ?? '';
|
||||
$new_password_confirm = $_POST["new_password_confirm"] ?? '';
|
||||
|
||||
// Token validieren
|
||||
if (empty($reset_token)
|
||||
|| !isset($_SESSION['reset_token'])
|
||||
|| $reset_token !== $_SESSION['reset_token']
|
||||
|| !isset($_SESSION['reset_token_expires'])
|
||||
|| $_SESSION['reset_token_expires'] < time()) {
|
||||
// Session-Daten aufräumen
|
||||
unset($_SESSION['reset_token'], $_SESSION['reset_user_id'], $_SESSION['reset_token_expires']);
|
||||
header("Location: reset-password.php?error=7");
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = (int)$_SESSION['reset_user_id'];
|
||||
|
||||
// Passwort-Validierung
|
||||
if (strlen($new_password) < 8 || !preg_match("/[a-z]/i", $new_password) || !preg_match("/[0-9]/", $new_password)) {
|
||||
header("Location: reset-password.php?step=newpassword&token=" . urlencode($reset_token) . "&error=5");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($new_password !== $new_password_confirm) {
|
||||
header("Location: reset-password.php?step=newpassword&token=" . urlencode($reset_token) . "&error=6");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Neues Passwort setzen
|
||||
$password_hash = password_hash($new_password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE user_login SET password_hash = ? WHERE user_id = ?");
|
||||
$stmt->execute([$password_hash, $user_id]);
|
||||
|
||||
// User-Daten laden für Mail und Vermerk
|
||||
$stmt = $pdo->prepare("SELECT mail, first_name, last_name FROM user_general_information WHERE user_id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$resetUserData = $stmt->fetch();
|
||||
|
||||
if ($resetUserData) {
|
||||
$loginUrl = "https://" . ($_SERVER['HTTP_HOST'] ?? intranet_env('INTRANET_FQDN')) . "/intranet_repo/projects/authorization/login.php";
|
||||
$greeting = !empty($resetUserData['first_name']) ? "Hallo {$resetUserData['first_name']}" : "Hallo";
|
||||
|
||||
$mailBetreff = "Passwort erfolgreich geändert";
|
||||
$mailNachricht = "{$greeting},\n\n";
|
||||
$mailNachricht .= "Ihr Passwort für das Intranet der NAK Reinickendorf wurde erfolgreich geändert.\n\n";
|
||||
$mailNachricht .= "Sie können sich ab sofort mit Ihrem neuen Passwort anmelden.";
|
||||
|
||||
send_intranet_mail($resetUserData['mail'], $mailBetreff, $mailNachricht, null, "intranet@nak-reinickendorf.de", "Jetzt anmelden", $loginUrl);
|
||||
|
||||
// Vermerk in erledigte Tasks
|
||||
$userName = trim(($resetUserData['first_name'] ?? '') . ' ' . ($resetUserData['last_name'] ?? ''));
|
||||
if (empty($userName)) $userName = $resetUserData['mail'];
|
||||
|
||||
$taskSubject = "Passwort selbst zurückgesetzt: {$userName}";
|
||||
$taskMessage = "{$userName} ({$resetUserData['mail']}) hat das eigene Passwort erfolgreich zurückgesetzt.";
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())");
|
||||
$stmt->execute([$userName, $resetUserData['mail'], $taskSubject, $taskMessage]);
|
||||
}
|
||||
|
||||
// Session-Daten aufräumen
|
||||
unset($_SESSION['reset_token'], $_SESSION['reset_user_id'], $_SESSION['reset_token_expires']);
|
||||
|
||||
header("Location: login.php?message=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
header("Location: reset-password.php");
|
||||
exit;
|
||||
?>
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php /* Name: reset-password.php
|
||||
Beschreibung: Passwort-Reset per SMS OTP (3 Schritte)
|
||||
- Schritt 1: E-Mail eingeben → OTP per SMS
|
||||
- Schritt 2: OTP-Code verifizieren
|
||||
- Schritt 3: Neues Passwort setzen */
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/functions.php';
|
||||
|
||||
$step = $_GET["step"] ?? "email";
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
<style>
|
||||
.login_button { position: relative; }
|
||||
.login_button.is-loading {
|
||||
color: transparent !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
.login_button.is-loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
margin: -11px 0 0 -11px;
|
||||
border: 3px solid rgba(255,255,255,0.35);
|
||||
border-top-color: #FFFFFF;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.7s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login_panel">
|
||||
|
||||
<?php if (isset($_GET["error"])): ?>
|
||||
<?php
|
||||
$errorMessages = [
|
||||
1 => "E-Mail-Adresse nicht gefunden oder nicht registriert.",
|
||||
2 => "Keine Telefonnummer hinterlegt. Bitte wenden Sie sich an den Administrator.",
|
||||
3 => "Ungültiger oder abgelaufener Code.",
|
||||
4 => "SMS konnte nicht gesendet werden. Bitte versuchen Sie es erneut.",
|
||||
5 => "Passwort muss mindestens 8 Zeichen, einen Buchstaben und eine Zahl enthalten.",
|
||||
6 => "Passwörter stimmen nicht überein.",
|
||||
7 => "Sitzung abgelaufen. Bitte starten Sie den Vorgang erneut."
|
||||
];
|
||||
$errorNum = (int)$_GET["error"];
|
||||
$errorText = $errorMessages[$errorNum] ?? "Unbekannter Fehler.";
|
||||
?>
|
||||
<div class="nak-toast nak-toast--error nak-toast--inline" id="nakToastErr">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
|
||||
<span class="nak-toast__text"><?= htmlspecialchars($errorText) ?></span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastErr').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_GET["success"]) && $_GET["success"] == 1): ?>
|
||||
<div class="nak-toast nak-toast--success nak-toast--inline" id="nakToastOk">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg></div>
|
||||
<span class="nak-toast__text">Passwort erfolgreich geändert. Sie können sich jetzt anmelden.</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastOk').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="login_content">
|
||||
<div class="nak-logo-link auth-logo">
|
||||
<img class="auth-logo__icon" src="/intranet_repo/projects/_central/img/nak-logo.svg" alt="NAK Logo">
|
||||
<div class="auth-logo__text">
|
||||
<div class="auth-logo__name">Neuapostolische Kirche</div>
|
||||
<div class="auth-logo__gemeinde">Berlin-Reinickendorf</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Passwort zurücksetzen</h2>
|
||||
|
||||
<?php if ($step === "email"): ?>
|
||||
<!-- SCHRITT 1: E-Mail eingeben -->
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Geben Sie Ihre E-Mail-Adresse ein. Ein Bestätigungscode wird an Ihre hinterlegte Telefonnummer und per Mail gesendet.</p>
|
||||
|
||||
<form action="reset-password-process.php" method="post" id="otpRequestForm">
|
||||
<input type="hidden" name="action" value="request_otp">
|
||||
<label for="email">E-Mailadresse</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="email" id="email" name="email" required>
|
||||
</div>
|
||||
<button class="login_button" type="submit" id="requestBtn">Code anfordern</button>
|
||||
</form>
|
||||
<script>
|
||||
document.getElementById('otpRequestForm').addEventListener('submit', function() {
|
||||
var btn = document.getElementById('requestBtn');
|
||||
btn.classList.add('is-loading');
|
||||
btn.disabled = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php elseif ($step === "verify"): ?>
|
||||
<!-- SCHRITT 2: Nur OTP-Code eingeben -->
|
||||
<?php $phone_masked = htmlspecialchars($_GET["phone"] ?? "***"); ?>
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Ein 6-stelliger Code wurde an die Nummer +49 <?= $phone_masked ?> und an Ihre E-Mail-Adresse gesendet.</p>
|
||||
|
||||
<form action="reset-password-process.php" method="post">
|
||||
<input type="hidden" name="action" value="verify_otp">
|
||||
<input type="hidden" name="user_id" value="<?= (int)($_GET["uid"] ?? 0) ?>">
|
||||
|
||||
<label for="otp_code">Bestätigungscode</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="text" id="otp_code" name="otp_code" maxlength="6" inputmode="numeric" pattern="[0-9]{6}" placeholder="000000" required autocomplete="one-time-code" style="text-align:center;font-size:1.4em;letter-spacing:8px;">
|
||||
</div>
|
||||
|
||||
<input class="login_button" type="submit" value="Code bestätigen">
|
||||
</form>
|
||||
|
||||
<?php elseif ($step === "newpassword"): ?>
|
||||
<!-- SCHRITT 3: Neues Passwort setzen (nur nach verifiziertem OTP) -->
|
||||
<p style="text-align:center;color:var(--gray-600);font-size:var(--font-size-sm);margin-bottom:var(--space-sm);">Ihr Code wurde bestätigt. Geben Sie nun Ihr neues Passwort ein.</p>
|
||||
|
||||
<form action="reset-password-process.php" method="post">
|
||||
<input type="hidden" name="action" value="set_password">
|
||||
<input type="hidden" name="reset_token" value="<?= htmlspecialchars($_GET["token"] ?? '') ?>">
|
||||
|
||||
<label for="new_password">Neues Passwort</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="password" id="new_password" name="new_password" required>
|
||||
</div>
|
||||
|
||||
<label for="new_password_confirm">Neues Passwort wiederholen</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="password" id="new_password_confirm" name="new_password_confirm" required>
|
||||
</div>
|
||||
|
||||
<input class="login_button" type="submit" value="Passwort ändern">
|
||||
</form>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="small_text" align="center">
|
||||
<br>
|
||||
<a href="login.php">Zurück zur Anmeldung</a><br>
|
||||
<br>
|
||||
Probleme beim Zurücksetzen?<br>
|
||||
<a href="#" onclick="openContactModal(); return false;">Admin kontaktieren</a>
|
||||
</div>
|
||||
</div><!-- EOD: login_content -->
|
||||
</div><!-- EOD: login_panel -->
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php /* Name: self-signup-process.php
|
||||
Beschreibung: Verarbeitung der Selbstregistrierung
|
||||
- Validierung der Eingaben
|
||||
- Speicherung in pending_registrations
|
||||
- Mail an Admin (samuel.bias@aol.de)
|
||||
- Eintrag in admin_messages */
|
||||
|
||||
$pdo = require_once($_SERVER['DOCUMENT_ROOT']."/intranet_repo/general_files/ini/database.php");
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/send_mail.php';
|
||||
|
||||
// Validierung
|
||||
if (empty($_POST["first_name"])) {
|
||||
die("Vorname ist erforderlich.");
|
||||
}
|
||||
if (empty($_POST["last_name"])) {
|
||||
die("Nachname ist erforderlich.");
|
||||
}
|
||||
if (!filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
|
||||
die("Gültige E-Mail-Adresse erforderlich.");
|
||||
}
|
||||
if (strlen($_POST["password"]) < 8) {
|
||||
die("Passwort muss mindestens 8 Zeichen lang sein.");
|
||||
}
|
||||
if (!preg_match("/[a-z]/i", $_POST["password"])) {
|
||||
die("Passwort muss mindestens einen Buchstaben enthalten.");
|
||||
}
|
||||
if (!preg_match("/[0-9]/", $_POST["password"])) {
|
||||
die("Passwort muss mindestens eine Zahl enthalten.");
|
||||
}
|
||||
if ($_POST["password"] !== $_POST["password_confirmation"]) {
|
||||
die("Passwörter stimmen nicht überein.");
|
||||
}
|
||||
|
||||
$email = trim($_POST["email"]);
|
||||
$first_name = trim($_POST["first_name"]);
|
||||
$last_name = trim($_POST["last_name"]);
|
||||
|
||||
// Prüfen ob E-Mail bereits existiert (in user_general_information oder pending_registrations)
|
||||
$checkSql = "SELECT COUNT(*) FROM user_general_information WHERE mail = ?";
|
||||
$stmt = $pdo->prepare($checkSql);
|
||||
$stmt->execute([$email]);
|
||||
$count1 = $stmt->fetchColumn();
|
||||
|
||||
$checkSql2 = "SELECT COUNT(*) FROM pending_registrations WHERE email = ? AND status = 'pending'";
|
||||
$stmt2 = $pdo->prepare($checkSql2);
|
||||
$stmt2->execute([$email]);
|
||||
$count2 = $stmt2->fetchColumn();
|
||||
|
||||
if ($count1 > 0 || $count2 > 0) {
|
||||
header("Location: self-signup.php?error=2");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Passwort hashen und Token generieren
|
||||
$password_hash = password_hash($_POST["password"], PASSWORD_DEFAULT);
|
||||
$token = bin2hex(random_bytes(32));
|
||||
|
||||
// In pending_registrations speichern
|
||||
$insertSql = "INSERT INTO pending_registrations (first_name, last_name, email, password_hash, token) VALUES (?, ?, ?, ?, ?)";
|
||||
$stmt = $pdo->prepare($insertSql);
|
||||
if (!$stmt) {
|
||||
header("Location: self-signup.php?error=1");
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!$stmt->execute([$first_name, $last_name, $email, $password_hash, $token])) {
|
||||
header("Location: self-signup.php?error=1");
|
||||
exit;
|
||||
}
|
||||
$pending_id = $pdo->lastInsertId();
|
||||
|
||||
// Admin-Nachricht in Inbox speichern
|
||||
$subject = "Neue Registrierungsanfrage: {$first_name} {$last_name}";
|
||||
$message_text = "Neue Selbstregistrierung:\n\nName: {$first_name} {$last_name}\nE-Mail: {$email}\n\nBitte im Adminpanel freischalten.";
|
||||
$data_json = json_encode(['pending_id' => $pending_id, 'token' => $token]);
|
||||
|
||||
$inboxSql = "INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, data_json) VALUES ('registration', ?, ?, ?, ?, ?)";
|
||||
$stmt = $pdo->prepare($inboxSql);
|
||||
$sender_name = "{$first_name} {$last_name}";
|
||||
$stmt->execute([$sender_name, $email, $subject, $message_text, $data_json]);
|
||||
|
||||
// Mail an Admin-Team (Admin + Technik)
|
||||
$admin_email = ADMIN_EMAIL;
|
||||
$mail_betreff = "Intranet: Neue Registrierungsanfrage von {$first_name} {$last_name}";
|
||||
$mail_nachricht = "Hallo Admin,\n\n";
|
||||
$mail_nachricht .= "Es liegt eine neue Registrierungsanfrage vor:\n\n";
|
||||
$mail_nachricht .= "Name: {$first_name} {$last_name}\n";
|
||||
$mail_nachricht .= "E-Mail: {$email}\n\n";
|
||||
$mail_nachricht .= "Bitte melden Sie sich im Adminpanel an, um die Anfrage zu bearbeiten.\n\n";
|
||||
$mail_nachricht .= "-- Intranet NAK Reinickendorf";
|
||||
|
||||
send_admin_team_mail($pdo, $mail_betreff, $mail_nachricht);
|
||||
|
||||
// Erfolg
|
||||
header("Location: self-signup.php?success=1");
|
||||
exit;
|
||||
?>
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php /* Name: self-signup.php
|
||||
Beschreibung: Selbstregistrierung - Nutzer kann sich eigenständig registrieren.
|
||||
Admin erhält Mail + Inbox-Nachricht zur Freischaltung. */
|
||||
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/parameters.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/ini/functions.php';
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr">
|
||||
<head>
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
|
||||
|
||||
<script src="just-validate.js" defer></script>
|
||||
<script src="validation.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login_panel">
|
||||
|
||||
<?php if (isset($_GET["error"])): ?>
|
||||
<?php if ($_GET["error"] == 1): ?>
|
||||
<div class="nak-toast nak-toast--error nak-toast--inline" id="nakToastErr">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
|
||||
<span class="nak-toast__text">Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastErr').classList.add('nak-toast--visible');});</script>
|
||||
<?php elseif ($_GET["error"] == 2): ?>
|
||||
<div class="nak-toast nak-toast--error nak-toast--inline" id="nakToastErr">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>
|
||||
<span class="nak-toast__text">Diese E-Mailadresse ist bereits registriert oder es liegt bereits eine Anfrage vor.</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastErr').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_GET["success"]) && $_GET["success"] == 1): ?>
|
||||
<div class="nak-toast nak-toast--success nak-toast--inline" id="nakToastOk">
|
||||
<div class="nak-toast__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg></div>
|
||||
<span class="nak-toast__text">Ihre Registrierungsanfrage wurde gesendet. Sie erhalten eine Benachrichtigung, sobald Ihr Konto freigeschaltet wurde.</span>
|
||||
</div>
|
||||
<script>requestAnimationFrame(function(){document.getElementById('nakToastOk').classList.add('nak-toast--visible');});</script>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="login_content">
|
||||
<div class="nak-logo-link" style="display:flex;align-items:flex-end;gap:12px;text-decoration:none;margin-bottom:24px;">
|
||||
<img src="/intranet_repo/projects/_central/img/nak-logo.svg" alt="NAK Logo" style="width:52px;height:52px;flex-shrink:0;">
|
||||
<div style="display:flex;flex-direction:column;justify-content:flex-end;line-height:1.2;">
|
||||
<div style="font-family:var(--font-primary);font-weight:500;font-size:0.875rem;color:var(--gray-900);white-space:nowrap;">Neuapostolische Kirche</div>
|
||||
<div style="font-family:var(--font-primary);font-weight:300;font-size:0.75rem;color:var(--gray-600);white-space:nowrap;">Berlin-Reinickendorf</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Registrierung beantragen</h2>
|
||||
<h3 class="no_margins" align="center">Ihr Antrag wird von einem Administrator geprüft und freigeschaltet.</h3>
|
||||
|
||||
<form action="self-signup-process.php" method="post" id="signup" novalidate>
|
||||
<label for="first_name"><br>Vorname</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="text" id="first_name" name="first_name" required>
|
||||
</div>
|
||||
|
||||
<label for="last_name">Nachname</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="text" id="last_name" name="last_name" required>
|
||||
</div>
|
||||
|
||||
<label for="email">E-Mailadresse</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="email" id="email" name="email" required>
|
||||
</div>
|
||||
|
||||
<label for="password">Passwort</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="password" id="password" name="password" required>
|
||||
</div>
|
||||
|
||||
<label for="password_confirmation">Passwort wiederholen</label>
|
||||
<div class="item">
|
||||
<input class="login_field" type="password" id="password_confirmation" name="password_confirmation" required>
|
||||
</div>
|
||||
|
||||
<input class="login_button" type="submit" value="Registrierung beantragen">
|
||||
</form>
|
||||
<div class="small_text" align="center">
|
||||
Sie haben bereits einen Account?
|
||||
<br>
|
||||
<a href="login.php">Anmelden</a>
|
||||
<br><br>
|
||||
Sie wurden bereits vom Admin vorregistriert?
|
||||
<br>
|
||||
<a href="signup.php">Direkt registrieren</a>
|
||||
</div>
|
||||
</div><!-- EOD: login_content -->
|
||||
</div><!-- EOD: login_panel -->
|
||||
|
||||
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||