Compare commits

..

54 Commits

Author SHA1 Message Date
d70c21c77f removed link profil 2025-07-11 23:45:26 +02:00
35fff7cc59 Merge remote-tracking branch 'origin/frontendBackendFinal' into frontendBackendFinal 2025-07-11 23:35:46 +02:00
ab1afa29a3 good changes 2025-07-11 23:33:11 +02:00
baf57fec49 Ki irgendwas gefixxed 2025-07-11 23:21:08 +02:00
906ca76332 fixed redirect error and added button to events. 2025-07-11 23:09:17 +02:00
f780888107 fixed the redirect
to handle everything properly
2025-07-11 22:55:51 +02:00
a881b3933d Fixed error and Implemented BuyTickets views Model and Controller. Added Button to Events and Added Styles 2025-07-11 22:43:29 +02:00
c306a59fec Fixed delete and update error. 2025-07-11 21:22:22 +02:00
7787cb2956 Added Create, Update and Delete to Events and added styles. 2025-07-11 21:16:42 +02:00
Karsten Tlotzek
d4534f9a11 CSS-Styles für Karten und Nachrichten aktualisiert: Flexbox-Layout hinzugefügt, Schriftgrößen und Abstände angepasst, sowie Farbänderungen für Statusboxen vorgenommen. 2025-07-11 18:24:40 +02:00
Karsten Tlotzek
07eba7762c News Überschrift und Erstellen Button zentriert 2025-07-11 18:10:06 +02:00
Karsten Tlotzek
b89714a6e7 Gutscheinverwaltung für Admins fertig gemacht:
Übersicht, Erstellen & Bearbeiten im einheitlichen Card-Design
Routing-Fehler nach Aktionen gefixt (Redirects & Erfolgsseiten) Gutscheine-Link in Navigation nur für Admins
2025-07-11 18:06:27 +02:00
Karsten Tlotzek
6cb75b0c1d News-Ansicht aufgeräumt & vereinheitlicht
- CSS-Klassen und Benennungen überall einheitlich gemacht (news-card, login-success usw.)
- Unnötige CSS-Regeln rausgeschmissen, Code jetzt viel schlanker
- Cards sehen jetzt überall gleich aus, egal wie viel Text drinsteht
- „Mehr lesen“-Link besser sichtbar gemacht
- Bugfix: Langer News-Text läuft nicht mehr aus der Card raus
- Generell: Viel code aufgeräumt, damit alles schicker und übersichtlicher ist!
2025-07-11 17:26:23 +02:00
7280cb0246 News-Bearbeitung gefixt: Feldnamen im Model an Controller & Formular angepasst, keine Notices mehr beim Editieren. 2025-07-08 10:38:27 +02:00
5f3ac9f78d Merge branch 'frontendBackendFinal' of https://git.bib.de/PBBFA23CSE/Bib-Arts into frontendBackendFinal 2025-07-08 10:29:03 +02:00
775b752d59 News-Admin-Workflow aufgebohrt:
- News können jetzt als Admin  erstellt und gelöscht werden, mit Zwischenseite zur Bestätigung.
- Fehler bei den Feldnamen im Model gefixt.
- Nach dem Anlegen/Löschen gibt’s jetzt wie beim Login/Registrieren eine kurze Erfolgsmeldung und automatischen Redirect.
- Includes und Redirects aufgeräumt, damit keine Warnungen mehr kommen.
2025-07-08 10:12:07 +02:00
3faec473ef Added Styles to Create and Update Event 2025-07-07 20:32:35 +02:00
a9944259b6 vorlage für create und update für event gemacht. 2025-07-07 14:50:05 +02:00
4f0f1e5f6d Navigationsleiste angepasst, je nach login zustand 2025-07-07 14:40:55 +02:00
e68c86c93e Merge branch 'frontendBackendFinal' of https://git.bib.de/PBBFA23CSE/Bib-Arts into frontendBackendFinal 2025-07-07 14:38:36 +02:00
a9997b3c63 Registrierung und Login aufgeräumt: Felder und Fehler angepasst, Formulardaten bleiben bei Fehlern erhalten, Navigation zeigt jetzt nur noch passende Links je nach Login-Status, Passwort-Fehler verständlich auf Deutsch. Alles einheitlich und benutzerfreundlich gemacht! 2025-07-07 14:31:32 +02:00
9ce7a6cfd3 fixed infos 2025-07-07 14:26:26 +02:00
ca757d1723 Merge branch 'frontendBackendFinal' of https://git.bib.de/PBBFA23CSE/Bib-Arts into frontendBackendFinal 2025-07-07 14:22:53 +02:00
717d361dbb showNews angebindet und zum laufen gebracht. 2025-07-07 14:19:52 +02:00
404e846418 logout von form zu button mit get request geändert 2025-07-07 12:46:49 +02:00
3ce61ace17 "Zwischen-Views" erstellt für Weiterleitung nach Login/Logout. Views einheitlich im div container class="inhalt". Error message nach fehlerhaftem login. 2025-07-07 12:43:25 +02:00
3dc68dd0bc forgot pw try to fix 2025-07-07 11:24:11 +02:00
b9fc6bcdd5 fixed Registration 2025-07-07 11:20:57 +02:00
a50b48592b fixed event 2025-07-07 11:15:49 +02:00
1691370db6 Merge branch 'frontendBackendFinal' of https://git.bib.de/PBBFA23CSE/Bib-Arts into frontendBackendFinal 2025-07-07 11:04:31 +02:00
a6b672ee7e Refactor Controller and models anhand der bibarts.sql und unbrauchbare Controllers und Models entfernt. 2025-07-07 11:03:59 +02:00
97c03d817e Initiales .sql script angepasst 2025-07-07 11:03:51 +02:00
877be4e567 Login Form updated 2025-07-07 11:01:54 +02:00
ef3349c6e4 fixed login and register with right linktos 2025-07-07 10:42:58 +02:00
415d8120e5 AuthController hinzugefügt 2025-07-07 10:35:49 +02:00
a4eef4e4e3 AuthController und methoden hinzugefügt. 2025-07-07 10:34:37 +02:00
37ee931954 Merge branch 'backend' into frontendBackendFinal 2025-07-07 10:06:42 +02:00
c6358b5ea6 fixed the warning 2025-07-07 09:13:05 +02:00
cc4bc791c9 added showTickets.phtml and added the TicketsController. 2025-07-07 09:08:39 +02:00
586322a189 fixed the <html> and <body> tags in all views 2025-07-07 08:42:26 +02:00
1416fd7fa0 Refactor all 2025-07-03 15:51:04 +02:00
16a91cc028 dingdagabum 2025-06-30 14:57:32 +02:00
cbd7b0f8cc Spaltennamen angepasst 2025-06-30 10:13:36 +02:00
db1b26f017 Merge remote-tracking branch 'refs/remotes/origin/frontend' into frontendbackendtest 2025-06-30 10:00:17 +02:00
Viktor Sergeev
3be7e1ecfd Dies und das 2025-06-27 11:09:14 +02:00
d8865cbd27 Controller und Tickets vereinheitlicht (CRUD) 2025-06-23 14:46:12 +02:00
66ff531ba4 Tickets erweitert 2025-06-23 11:11:18 +02:00
1964cadd8c Standardmethoden für Standort und News.Events erweitert 2025-06-23 11:10:46 +02:00
6e3e3708b2 EventController, TicketController + Model + essenzielle Funktionen 2025-06-16 15:12:03 +02:00
Viktor Sergeev
0cff38b71f real 2025-06-16 15:11:49 +02:00
5bde268b89 Merge remote-tracking branch 'origin/develop' into develop 2025-06-12 16:30:43 +02:00
5cef69ae81 added database creation sql with test data karsten kann nicht coden 2025-06-12 16:29:00 +02:00
f3699cb287 Added .gitignore 2025-06-12 16:27:03 +02:00
1f8e7dc67b Test 2025-06-12 16:24:31 +02:00
69 changed files with 3178 additions and 484 deletions

193
.gitignore vendored Normal file
View File

@ -0,0 +1,193 @@
# Created by https://www.toptal.com/developers/gitignore/api/intellij,windows,macos,git
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij,windows,macos,git
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/encodings.xml
.idea/php.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
# Azure Toolkit for IntelliJ plugin
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
.idea/**/azureSettings.xml
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### macOS Patch ###
# iCloud generated files
*.icloud
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# End of https://www.toptal.com/developers/gitignore/api/intellij,windows,macos,git

6
.idea/sqldialects.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/contact.sql" dialect="GenericSQL" />
</component>
</project>

View File

@ -1,202 +1,655 @@
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
body {
background-color: #DFF0F2;
color: black;
font-size: 15px;
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
width: 100vw;
max-width: 100vw;
overflow-x: hidden;
}
a {
color: black;
text-decoration: none;
}
#navigation {
display: flex;
justify-content: center;
position: sticky;
top: 0;
z-index: 1000;
background: #BAC8D4;
width: 100vw;
}
.link-container {
display: grid;
width: 80%;
grid-template-columns: 20% 20% 56% 4%;
background-color: #BAC8D4;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
}
.links {
display: flex;
align-items: center;
font-size: 25px;
}
#logo {
height: 60px;
width: 170px;
background-image: url("../images/bibArts.png");
background-position: center;
background-size: contain;
}
#footer {
position: relative;
bottom: 0;
left: 0;
width: 100vw;
height: 180px;
background-color: #BAC8D4;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-shrink: 0;
z-index: 999;
padding: 10px 0;
}
.container-zahlungsmittel {
grid-column: 5;
justify-content: right;
}
.header-zahlungsarten {
padding-right: 15px;
text-align: right;
}
.inhalt {
flex: 1 1 auto;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
min-height: 0;
min-width: 0;
margin: 0;
padding: 0 2vw;
box-sizing: border-box;
}
body {
background-color: #ffffff;
color: #666;
font-size: 15px;
.zahlungsmittel-img {
height: 41px;
width: 284px;
background-image: url("../images/Zahlungsmittel.png");
background-position: center;
background-size: contain;
justify-self: right;
}
h1 {
margin: 10px;
color: #4d4d4d;
font-size: 30px;
.line {
width: 97%;
height: 1px;
background-color: grey;
justify-self: center;
grid-column-start: 1;
grid-column-end: 6;
}
h1 span {
color: orange;
font-size: 40px;
}
h2 {
color: orange;
padding: 10px 0 0 10px;
}
main {
margin-top: 135px;
padding: 10px;
}
#wrapper {
max-width: 600px;
margin: 0 auto;
background-color: #4d4d4d;
color: white;
}
.msg {
text-align: center;
font-size: 17px;
font-weight: 700;
}
.msg a {
text-decoration: none;
color: #09add0;
.link-impressum {
padding-left: 30px;
}
.msg a:hover {
color: orange;
.text-bib {
grid-column: 5;
justify-self: right;
padding-right: 30px;
}
nav ul {
list-style-type: none;
padding: 0;
display: inline-block;
margin: 0;
}
nav li {
float: left;
text-align: center;
}
nav li a {
display: block;
width: 100px;
height: 30px;
border: 1px solid #4d4d4d;
background-color: #4d4d4d;
color: white;
text-decoration: none;
margin: 5px;
text-align: center;
line-height: 30px;
}
nav li a:hover {
background-color: orange;
}
nav {
position: fixed;
.container-welcome-inhalt {
display: grid;
grid-template-columns: 1fr 1fr;
width: 100%;
max-width: 900px;
min-height: 200px;
border-radius: 10px;
background: white;
top: 0px;
width: 600px;
text-align: center;
padding-top: 10px;
box-shadow: 0 2px 16px rgba(0,0,0,0.08);
justify-items: center;
align-items: center;
box-sizing: border-box;
padding: 10px 0;
}
#metanavi {
color: #4d4d4d;
font-weight: bold;
margin-bottom: 5px;
.beispiel-austellung1-img, .beispiel-austellung2-img {
height: 200px;
width: 90vw;
max-width: 320px;
background-position: center;
background-size: contain;
border-radius: 10px;
}
#metanavi a {
background: #09add0;
border: none;
width: 100px;
margin: 0 5px 0 5px;
float: right;
padding: 2px;
border-radius: 5px;
color:#fff;
cursor:pointer;
font-size: 12px;
text-decoration: none;
text-align: center;
}
#metanavi a:hover {
background: orange;
}
.articleImg {
.form-container {
background-color: #BAC8D4;
width: 100%;
border: 2px solid lightskyblue;
padding: 5px;
margin: 0 0 15px 0;
max-width: 400px;
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
box-sizing: border-box;
padding: 32px 24px 24px 24px;
margin: 32px auto;
}
.welcomeImg {
.form-horizontal {
width: 100%;
padding: 5px;
}
.articleInfo {
font-weight: bold;
}
/*** Formulare ***/
form {
width: 440px;
margin: auto;
}
label {
width: 120px;
display: inline-block;
margin: 5px 15px 10px 0;
vertical-align: top;
text-align: right;
}
label.errorMsg {
width: 420px;
display: inline-block;
margin: 0 5px 15px 0;
vertical-align: top;
text-align: right;
color: orange;
}
input {
width: 300px;
}
input[type="submit"] {
width: 100px;
margin-left: 330px;
}
form textarea {
width: 300px;
height: 150px;
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 10px;
}
form select {
width: 300px;
.form-horizontal label {
margin-bottom: 2px;
}
/*** Loesung Workshop-Seite ***/
.textContent {
padding: 0 10px 0 30px;
.form-horizontal input[type="text"],
.form-horizontal input[type="email"],
.form-horizontal input[type="password"] {
width: 100%;
padding: 8px 10px;
border: 1px solid #BAC8D4;
border-radius: 4px;
font-size: 1rem;
box-sizing: border-box;
background: #fff;
}
.form-horizontal input[type="date"],
.form-horizontal input[type="number"],
.form-horizontal select,
.form-horizontal textarea {
width: 100%;
padding: 8px 10px;
border: 1px solid #BAC8D4;
border-radius: 4px;
font-size: 1rem;
box-sizing: border-box;
background: #fff;
}
.form-horizontal textarea {
resize: vertical;
min-height: 100px;
}
.form-horizontal button {
width: 100%;
padding: 10px 0;
border: none;
border-radius: 4px;
background: #4d4d4d;
color: #fff;
font-size: 1rem;
margin-top: 8px;
cursor: pointer;
transition: background 0.2s;
}
.form-horizontal button:hover {
background: #333;
}
.button-register {
width: 100%;
padding: 10px 0;
border: none;
border-radius: 4px;
background: #4d4d4d;
color: #fff;
font-size: 1rem;
margin-top: 8px;
cursor: pointer;
transition: background 0.2s;
}
.button-register:hover {
background: #333;
}
.login-error, .form-error {
background: #ffe0e0;
color: #b30000;
border: 1px solid #ffb3b3;
border-radius: 6px;
padding: 10px 16px;
margin-bottom: 18px;
width: 100%;
text-align: center;
}
@media (max-width: 529px) {
.textContent {
padding: 15px 0 0 0;
@media (max-width: 600px) {
body {
font-size: 14px;
width: 100vw;
max-width: 100vw;
overflow-x: hidden;
}
#navigation {
width: 100vw;
min-width: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
}
.event h3 {
margin: 15px 0 5px 0;
font-size: 20px;
text-align: left;
.link-container {
width: 100vw;
min-width: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
row-gap: 8px;
border-radius: 0;
padding: 0 4px;
}
.orange {
color: orange;
display: block;
.links {
font-size: 18px;
margin: 0 0 5px 0;
justify-content: center;
align-items: center;
padding: 6px 0;
text-align: center;
width: 100%;
}
#logo {
width: 120px;
height: 40px;
margin: 0 auto 8px auto;
display: flex;
justify-content: center;
align-items: center;
}
.container-welcome-inhalt {
grid-template-columns: 1fr;
width: 100vw;
max-width: 100vw;
min-height: 0;
padding: 8px 0;
}
.beispiel-austellung1-img, .beispiel-austellung2-img {
width: 90vw;
max-width: 98vw;
height: 120px;
margin-bottom: 10px;
}
.inhalt {
width: 100vw;
min-width: 0;
max-width: 100vw;
padding: 0 2vw;
box-sizing: border-box;
flex-direction: column;
align-items: stretch;
}
#footer {
width: 100vw;
height: auto;
min-height: 120px;
padding: 10px 0 10px 0;
font-size: 13px;
}
.container-zahlungsmittel {
width: 100vw;
text-align: center;
padding: 0;
}
.header-zahlungsarten {
font-size: 1.1em;
padding-right: 0;
text-align: center;
}
.zahlungsmittel-img {
width: 90vw;
max-width: 200px;
height: 30px;
margin: 0 auto;
}
.line {
width: 95vw;
}
.link-impressum, .link-datenschutz, .link-nutzungsbedingungen {
display: block;
padding: 2px 0;
text-align: center;
}
.text-bib {
display: block;
text-align: center;
padding: 0;
}
.mobile-only {
display: block !important;
}
.form-container {
position: static;
width: 95vw;
max-width: 400px;
height: auto;
margin: 24px auto;
padding: 16px 8px;
box-sizing: border-box;
}
.content-container {
position: static;
width: 95vw;
max-width: 400px;
height: auto;
margin: 24px auto;
padding: 16px 8px;
box-sizing: border-box;
}
.form-container h1 {
font-size: 1.5em;
text-align: center;
}
.content-container h1 {
font-size: 1.5em;
text-align: center;
}
.form-container form,
.form-container label,
.form-container input {
width: 100%;
max-width: 100%;
box-sizing: border-box;
}
.form-container button,
.form-container a {
width: 100%;
max-width: 100%;
margin-top: 8px;
text-align: center;
box-sizing: border-box;
}
#nav-toggle-btn {
display: block;
background: none;
border: none;
font-size: 2em;
cursor: pointer;
margin: 0 auto 8px auto;
transition: transform 0.2s;
}
.nav-links {
display: none;
flex-direction: column;
align-items: center;
width: 100%;
transition: max-height 0.3s ease;
overflow: hidden;
}
.nav-links.open {
display: flex;
}
#nav-toggle-btn.open {
transform: rotate(180deg);
}
}
@media (min-width: 601px) {
.mobile-only {
display: none !important;
}
.desktop-only {
display: block !important;
}
#nav-toggle-btn {
display: none;
}
.nav-links {
display: flex !important;
flex-direction: row;
align-items: center;
width: auto;
gap: 32px;
}
.nav-links .links {
margin: 0 12px;
}
.content-container {
width: 90vw;
max-width: 1200px;
margin: 24px auto;
padding: 16px 8px;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
}
.news-header {
text-align: center;
margin-bottom: 24px;
}
.news-header h2 {
margin-bottom: 16px;
}
.news-header .admin-btn {
margin: 0 auto;
display: inline-block;
}
.event-header {
text-align: center;
margin-bottom: 24px;
}
.event-header h2 {
margin-bottom: 16px;
}
.event-header .admin-btn {
margin: 0 auto;
display: inline-block;
}
.card--wide {
max-width: 700px;
width: auto;
margin: 0 auto;
display: block;
overflow-wrap: break-word;
}
}
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
background: #fff;
border-radius: 10px;
box-shadow: 0 2px 12px rgba(0,0,0,0.07);
margin: 24px 0;
overflow: hidden;
}
thead th {
background: #BAC8D4;
color: #222;
font-weight: 600;
padding: 12px 8px;
text-align: left;
border-bottom: 2px solid #e0e0e0;
}
tbody td {
padding: 10px 8px;
border-bottom: 1px solid #f0f0f0;
vertical-align: top;
}
tbody tr:last-child td {
border-bottom: none;
}
tbody tr:hover {
background: #f5faff;
}
.admin-btn, .admin-btn:visited {
display: inline-block;
background: #4d4d4d;
color: #fff;
border-radius: 5px;
padding: 7px 16px;
margin: 8px 0 12px 0;
text-decoration: none;
font-size: 1em;
font-weight: 500;
transition: background 0.2s;
}
.admin-btn:hover {
background: #222;
color: #fff;
}
td a {
color: #09add0;
text-decoration: underline;
margin: 0 4px;
font-size: 0.98em;
}
td a:hover {
color: #007b9e;
}
.news-cards {
display: flex;
flex-wrap: wrap;
gap: 24px;
justify-content: flex-start;
margin: 24px 0;
}
.card {
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
padding: 20px 18px 16px 18px;
max-width: 340px;
min-width: 220px;
flex: 1 1 300px;
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 0;
overflow-wrap: break-word;
overflow: hidden;
}
.card h3 {
margin: 0 0 10px 0;
font-size: 1.25em;
color: #222;
font-weight: bold;
border-bottom: 2px solid #e0e0e0;
padding-bottom: 6px;
}
.card .news-date {
font-size: 0.95em;
color: #888;
margin-bottom: 16px;
margin-top: 2px;
display: block;
letter-spacing: 0.5px;
}
.card .news-desc {
font-size: 1em;
color: #333;
margin-bottom: 14px;
white-space: pre-line;
}
.card .admin-btn {
align-self: flex-end;
margin: 0 0 0 8px;
padding: 6px 12px;
font-size: 0.97em;
}
.card--wide {
max-width: 700px;
width: 100%;
margin: 0 auto;
display: block;
overflow: visible;
overflow-wrap: break-word;
}
.news-desc a {
color: #007b9e;
font-weight: 600;
text-decoration: underline;
margin-left: 4px;
transition: color 0.2s;
}
.news-desc a:hover {
color: #09add0;
text-decoration: underline;
}
.news-card-actions {
margin-top: auto;
display: flex;
gap: 12px;
}
.news-desc {
min-height: 80px;
margin-bottom: 14px;
}
@media (max-width: 700px) {
.news-cards {
flex-direction: column;
gap: 16px;
}
.card {
max-width: 98vw;
min-width: unset;
width: 100%;
}
}
.status-box {
background: #e6f9e6;
color: #217a21;
border: 1px solid #b3e6b3;
border-radius: 6px;
padding: 10px 16px;
margin-bottom: 18px;
width: 100%;
text-align: center;
}
.error-box {
background: #ffe0e0;
color: #b30000;
border: 1px solid #ffb3b3;
border-radius: 6px;
padding: 10px 16px;
margin-bottom: 18px;
width: 100%;
text-align: center;
}
.gutschein-header-block {
width: 100%;
max-width: 1100px;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 18px;
}
.gutschein-table {
max-width: 1100px;
width: 100%;
margin: 0 auto;
}
.event-details {
background: white;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.event-details h2 {
margin-top: 0;
color: #333;
font-size: 1.5em;
}
.event-details p {
margin: 8px 0;
line-height: 1.4;
}
.event-details strong {
color: #4d4d4d;
}

View File

@ -0,0 +1,150 @@
<?php
namespace Blog\Controller;
use Blog\Model\AuthModel;
class AuthController
{
private $model;
private $view;
public function __construct($view) {
$this->model = new AuthModel();
$this->view = $view;
}
public function showLoginForm() {
$this->view->setVars([
'labels' => [
"email" => "E-Mail-Adresse",
"password" => "Passwort",
"password_repeat" => "Passwort wiederholen",
"old_password" => "Altes Passwort"
],
'errors' => $_SESSION['auth_errors'] ?? [],
'validData' => $_SESSION['auth_validData'] ?? []
]);
unset($_SESSION['auth_errors'], $_SESSION['auth_validData']);
}
public function showRegistrationForm() {
$this->view->setVars([
'labels' => [
"email" => "E-Mail-Adresse",
"password" => "Passwort",
"password_repeat" => "Passwort wiederholen",
"old_password" => "Altes Passwort"
],
'errors' => $_SESSION['auth_errors'] ?? [],
'validData' => $_SESSION['auth_validData'] ?? []
]);
unset($_SESSION['auth_errors'], $_SESSION['auth_validData']);
}
public function login() {
$email = $_POST['email'];
$password = $_POST['password'];
$result = $this->model->login($email, $password);
if ($result['success']) {
$_SESSION['user'] = $result['user']['email'];
$_SESSION['is_admin'] = $result['user']['is_admin'];
$this->view->setDoMethodName('showLoginSuccess');
} else {
$this->view->setVars([
'errors' => ['login' => $result['error']],
'validData' => ['email' => $email],
'loginSuccess' => false
]);
$this->view->setDoMethodName('showLoginForm');
}
}
public function register() {
$data = [
'first_name' => $_POST['first_name'] ?? '',
'last_name' => $_POST['last_name'] ?? '',
'street' => $_POST['street'] ?? '',
'house_number' => $_POST['house_number'] ?? '',
'postal_code' => $_POST['postal_code'] ?? '',
'city' => $_POST['city'] ?? '',
'country' => $_POST['country'] ?? '',
'phone' => $_POST['phone'] ?? '',
'email' => $_POST['email'] ?? '',
'password' => $_POST['password'] ?? '',
'password_repeat' => $_POST['password_repeat'] ?? '',
'is_admin' => $_POST['isAdmin'] ?? false,
];
$result = $this->model->register($data);
if ($result === true) {
$this->view->setDoMethodName('showRegistrationSuccess');
} else {
if (is_array($result)) {
$errors['register'] = implode('<br>', $result);
} else {
$errors['register'] = is_string($result) ? $result : "Registrierung fehlgeschlagen.";
}
$this->view->setVars(['errors' => $errors, 'validData' => $data]);
$this->view->setDoMethodName('showRegistrationForm');
}
}
public function forgotPassword() {
$email = $_POST['email'] ?? '';
if (empty($email)) {
$_SESSION['auth_errors']['email'] = "Bitte E-Mail-Adresse angeben.";
header("Location: /?controller=Auth&do=showAuthForm");
exit;
}
$this->model->pwForgot($email);
header("Location: /?controller=Auth&do=showConfirmation&msg=pwforgot");
exit;
}
public function changePassword() {
$email = $_POST['email'] ?? '';
$oldpw = $_POST['old_password'] ?? '';
$newpw = $_POST['password'] ?? '';
$repeat = $_POST['password_repeat'] ?? '';
if (!$this->model->checkDoublePw($newpw, $repeat)) {
$_SESSION['auth_errors']['password'] = "Neue Passwörter stimmen nicht überein.";
header("Location: /?controller=Auth&do=showAuthForm");
exit;
}
$result = $this->model->updatePassword($email, $oldpw, $newpw);
if ($result === true) {
header("Location: /?controller=Auth&do=showConfirmation&msg=pwchange");
exit;
} else {
$_SESSION['auth_errors']['password'] = is_string($result) ? $result : "Fehler beim Aktualisieren des Passworts.";
header("Location: /?controller=Auth&do=showAuthForm");
exit;
}
}
public function showConfirmation() {
$messages = [
'login' => "Login erfolgreich.",
'register' => "Registrierung erfolgreich.",
'pwforgot' => "Ein temporäres Passwort wurde an Ihre E-Mail gesendet.",
'pwchange' => "Passwort erfolgreich geändert."
];
$msgKey = $_GET['msg'] ?? '';
$message = $messages[$msgKey] ?? "Aktion erfolgreich.";
$this->view->setVars(['message' => $message]);
$this->view->render('auth/confirmation');
}
public function logout() {
unset($_SESSION['user']);
session_destroy();
$this->view->setDoMethodName('showLogoutSuccess');
}
}

View File

@ -1,56 +0,0 @@
<?php
namespace Blog\Controller;
use Blog\Model\ContactModel;
class ContactController
{
protected $view;
private $db;
private $validData = array();
private $errors = array();
private $labels = array("name" => "Name", "email" => "E-Mail-Adresse", "content" => "Nachricht");
public function __construct($view)
{
$this->db = new ContactModel();
$this->view = $view;
}
public function showContactForm()
{
$this->view->setVars([
'labels' => $this->labels,
'validData' => $this->validData,
'errors' => $this->errors
]);
}
public function showConfirmation()
{
}
public function validateForm(){
foreach ($this->labels as $index => $value) {
if (!isset($_POST[$index]) || empty($_POST[$index])) {
$this->errors[$index] = "Bitte " . $value . " angeben";
} else {
$this->validData[$index] = $_POST[$index];
}
}
if (count($this->errors) > 0) {
$this->view->setDoMethodName("showContactForm");
$this->showContactForm();
} else {
if ($this->db->writeContactData($this->validData)) {
$this->view->setDoMethodName("showConfirmation");
$this->showConfirmation();
}
}
}
}
?>

View File

@ -0,0 +1,161 @@
<?php
namespace Blog\Controller;
use Blog\Model\EventModel;
use Blog\Model\StandortModel;
class EventController {
private $model;
private $view;
public function __construct($view) {
$this->model = new EventModel();
$this->view = $view;
}
public function showEvents() {
$events = $this->model->getEvents();
$this->view->setVars([
'events' => $events
]);
}
public function createEvent() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=Event&do=showEvents');
exit;
}
$data = [
'name' => $_POST['name'] ?? '',
'start_date' => $_POST['start_date'] ?? '',
'end_date' => $_POST['end_date'] ?? '',
'location_id' => $_POST['location_id'] ?? '',
'description' => $_POST['description'] ?? '',
'max_tickets' => $_POST['max_tickets'] ?? '',
'ticket_price' => $_POST['ticket_price'] ?? ''
];
$errors = [];
if (empty($data['name']) || empty($data['start_date']) || empty($data['end_date']) || empty($data['location_id']) || empty($data['description']) || empty($data['max_tickets']) || empty($data['ticket_price'])) {
$errors['event'] = 'Bitte alle Felder ausfüllen.';
}
if (!empty($errors)) {
$standortModel = new StandortModel();
$locations = $standortModel->getStandorte();
$this->view->setVars(['errors' => $errors, 'validData' => $data, 'locations' => $locations]);
$this->view->setDoMethodName('showCreateEvent');
return;
}
$this->model->createEvent($data);
$this->view->setDoMethodName('showCreateForwarding');
}
public function editEventForm() {
$id = $_GET['ausstellungid'];
$event = $this->model->getEvent($id);
$this->view->setVars(['event' => $event]);
}
public function updateEvent() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=Event&do=showEvents');
exit;
}
$id = $_POST['id'] ?? null;
$data = [
'name' => $_POST['name'] ?? '',
'start_date' => $_POST['start_date'] ?? '',
'end_date' => $_POST['end_date'] ?? '',
'location_id' => $_POST['location_id'] ?? '',
'description' => $_POST['description'] ?? '',
'max_tickets' => $_POST['max_tickets'] ?? '',
'ticket_price' => $_POST['ticket_price'] ?? ''
];
$errors = [];
if (empty($data['name']) || empty($data['start_date']) || empty($data['end_date']) || empty($data['location_id']) || empty($data['description']) || empty($data['max_tickets']) || empty($data['ticket_price'])) {
$errors['event'] = 'Bitte alle Felder ausfüllen.';
}
if (!empty($errors)) {
$standortModel = new StandortModel();
$location = $standortModel->getStandort($data['location_id']);
$eventView = [
'id' => $id,
'name' => $data['name'],
'start_date' => $data['start_date'],
'end_date' => $data['end_date'],
'location_id' => $data['location_id'],
'location_name' => $location['city'] ?? '',
'description' => $data['description'],
'max_tickets' => $data['max_tickets'],
'ticket_price' => $data['ticket_price'],
];
$this->view->setVars(['event' => $eventView, 'errors' => $errors]);
$this->view->setDoMethodName('showUpdateEvent');
return;
}
$this->model->updateEvent($id, $data);
$this->view->setDoMethodName('showUpdateForwarding');
}
public function deleteEvent() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=Event&do=showEvents');
exit;
}
$id = $_GET['event_id'] ?? null;
if ($id) {
$this->model->deleteEvent($id);
$this->view->setVars(['id' => $id]);
$this->view->setDoMethodName('deleteEvent');
} else {
header('Location: index.php?controller=Event&do=showEvents');
exit;
}
}
public function showUpdateEvent() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=Event&do=showEvents');
exit;
}
$id = $_GET['event_id'] ?? null;
if (!$id) {
$this->view->setVars(['error' => 'Keine Event-ID angegeben.']);
return;
}
$event = $this->model->getEvent($id);
if (!$event) {
$this->view->setVars(['error' => 'Event nicht gefunden.']);
return;
}
$standortModel = new StandortModel();
$location = $standortModel->getStandort($event['location_id']);
$eventView = [
'id' => $event['event_id'],
'name' => $event['name'],
'start_date' => $event['start_date'],
'end_date' => $event['end_date'],
'location_id' => $event['location_id'],
'location_name' => $location['city'] ?? '',
'description' => $event['description'],
'max_tickets' => $event['max_tickets'],
'ticket_price' => $event['ticket_price'],
];
$this->view->setVars(['event' => $eventView, 'errors' => []]);
}
public function showCreateEvent() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=Event&do=showEvents');
exit;
}
$standortModel = new StandortModel();
$locations = $standortModel->getStandorte();
$this->view->setVars([
'locations' => $locations,
'errors' => [],
'validData' => []
]);
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace Blog\Controller;
use Blog\Model\GutscheinModel;
class GutscheinController {
private $model;
private $view;
public function __construct($view) {
$this->model = new GutscheinModel();
$this->view = $view;
}
public function showGutscheine() {
$gutscheine = $this->model->getGutscheine();
$this->view->setVars(['gutscheine' => $gutscheine]);
}
public function createGutscheinForm() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php');
exit;
}
$this->view->setDoMethodName('createGutscheinForm');
}
public function createGutschein() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php');
exit;
}
$data = [
'code' => $_POST['code'] ?? null,
'discount' => $_POST['discount'] ?? null,
'event_id' => $_POST['event_id'] ?? null,
'valid_until' => $_POST['valid_until'] ?? null
];
$this->model->createGutschein($data);
$this->view->setDoMethodName('showCreateSuccess');
}
public function editGutscheinForm() {
$id = $_GET['gutscheinid'];
if ($id) {
$gutschein = $this->model->getGutschein($id);
$this->view->setVars(['gutschein' => $gutschein]);
}
}
public function updateGutschein() {
$id = $_POST['gutscheinid'];
$data = [
'code' => $_POST['code'] ?? null,
'discount' => $_POST['discount'] ?? null,
'event_id' => $_POST['event_id'] ?? null,
'valid_until' => $_POST['valid_until'] ?? null
];
$this->model->updateGutschein($id, $data);
header('Location: index.php?controller=Gutschein&do=adminVerwaltung');
exit;
}
public function deleteGutschein() {
$id = $_GET['gutscheinid'] ?? null;
$this->model->deleteGutschein($id);
header('Location: index.php?controller=Gutschein&do=adminVerwaltung');
exit;
}
public function adminVerwaltung() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php');
exit;
}
$gutscheine = $this->model->getGutscheine();
$this->view->setVars(['gutscheine' => $gutscheine]);
$this->view->setDoMethodName('showGutscheine');
}
}

View File

@ -0,0 +1,121 @@
<?php
namespace Blog\Controller;
use Blog\Model\NewsModel;
class NewsController {
private $model;
private $view;
public function __construct($view) {
$this->model = new NewsModel();
$this->view = $view;
}
public function showNews() {
$news = $this->model->getNews();
$this->view->setVars(['news' => $news]);
}
public function createNews() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=News&do=showNews');
exit;
}
$data = [
'name' => $_POST['name'] ?? '',
'description' => $_POST['description'] ?? '',
'date' => $_POST['date'] ?? date('Y-m-d'),
];
$errors = [];
if (empty($data['name']) || empty($data['description']) || empty($data['date'])) {
$errors['news'] = 'Bitte alle Felder ausfüllen.';
}
if (!empty($errors)) {
$this->view->setVars(['errors' => $errors, 'validData' => $data]);
$this->view->setDoMethodName('createNewsForm');
return;
}
$this->model->createNews($data);
$this->view->setDoMethodName('showCreateSuccess');
}
public function createNewsForm() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=News&do=showNews');
exit;
}
$this->view->setVars([
'errors' => [],
'validData' => []
]);
}
public function editNewsForm() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=News&do=showNews');
exit;
}
$id = $_GET['id'] ?? null;
if ($id) {
$news = $this->model->getNewsById($id);
$validData = [
'name' => $news['name'] ?? '',
'description' => $news['description'] ?? '',
'date' => $news['date'] ?? date('Y-m-d'),
];
$this->view->setVars(['validData' => $validData, 'id' => $id, 'errors' => []]);
}
}
public function updateNews() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=News&do=showNews');
exit;
}
$id = $_POST['id'] ?? null;
$data = [
'name' => $_POST['name'] ?? '',
'description' => $_POST['description'] ?? '',
'date' => $_POST['date'] ?? date('Y-m-d'),
];
$errors = [];
if (empty($data['name']) || empty($data['description']) || empty($data['date'])) {
$errors['news'] = 'Bitte alle Felder ausfüllen.';
}
if (!empty($errors)) {
$this->view->setVars(['errors' => $errors, 'validData' => $data, 'id' => $id]);
$this->view->setDoMethodName('editNewsForm');
return;
}
$this->model->updateNews($id, $data);
$this->view->setDoMethodName('showEditSuccess');
}
public function deleteNews() {
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
header('Location: index.php?controller=News&do=showNews');
exit;
}
$id = $_GET['id'] ?? null;
if ($id) {
$this->model->deleteNews($id);
}
$this->view->setDoMethodName('showDeleteSuccess');
}
public function showNewsDetail() {
$id = $_GET['id'] ?? null;
if ($id) {
$news = $this->model->getNewsById($id);
if ($news) {
$this->view->setVars(['news' => $news]);
return;
}
}
header('Location: index.php?controller=News&do=showNews');
exit;
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Blog\Controller;
class ProfileController {
function showProfile()
{
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Blog\Controller;
use Blog\Model\StandortModel;
class StandortController {
private $model;
private $view;
public function __construct($view) {
$this->model = new StandortModel();
$this->view = $view;
}
public function showStandorte() {
$standorte = $this->model->getStandorte();
$this->view->setVars(['standorte' => $standorte]);
}
public function createStandort() {
$data = [
'straße' => $_POST['straße'],
'hausnr' => $_POST['hausnr'],
'postleitzahl' => $_POST['postleitzahl'],
'ort' => $_POST['ort'],
'land' => $_POST['land'],
'tel' => $_POST['tel'],
'email' => $_POST['email']
];
$erg = $this->model->createStandort($data);
$this->view->setVars(['standort' => $erg]);
}
public function editStandortForm() {
$id = $_GET['standortid'];
$standort = $this->model->getStandort($id);
$this->view->setVars(['standort' => $standort]);
}
public function updateStandort() {
$id = $_POST['standortid'];
$data = [
'straße' => $_POST['straße'],
'hausnr' => $_POST['hausnr'],
'postleitzahl' => $_POST['postleitzahl'],
'ort' => $_POST['ort'],
'land' => $_POST['land'],
'tel' => $_POST['tel'],
'email' => $_POST['email']
];
$erg = $this->model->updateStandort($id, $data);
$this->view->setVars(['standort' => $erg]);
}
public function deleteStandort() {
$id = $_GET['standortid'] ?? null;
$this->model->deleteStandort($id);
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace Blog\Controller;
use Blog\Model\TicketModel;
use Blog\Model\EventModel;
use Blog\Model\StandortModel;
class TicketController {
private $ticketModel;
private $eventModel;
private $view;
public function __construct($view) {
$this->ticketModel = new TicketModel();
$this->eventModel = new EventModel();
$this->view = $view;
}
public function showTickets() {
if (!isset($_SESSION['user_id'])) {
$this->view->setVars(['redirect' => 'index.php?controller=Auth&do=showLoginForm']);
return;
}
$tickets = $this->ticketModel->getUserTickets($_SESSION['user_id']);
$this->view->setVars(['tickets' => $tickets]);
}
public function showBuyTicketForm() {
if (!isset($_SESSION['user_id'])) {
$this->view->setVars(['redirect' => 'index.php?controller=Auth&do=showLoginForm']);
return;
}
$event_id = $_GET['event_id'] ?? null;
if (!$event_id) {
$this->view->setVars(['redirect' => 'index.php?controller=Event&do=showEvents']);
return;
}
$event = $this->eventModel->getEvent($event_id);
if (!$event) {
$this->view->setVars(['redirect' => 'index.php?controller=Event&do=showEvents']);
return;
}
// Check if user already has a ticket for this event
$hasTicket = $this->ticketModel->hasTicket($_SESSION['user_id'], $event_id);
$this->view->setVars([
'event' => $event,
'hasTicket' => $hasTicket['count'] > 0
]);
}
public function buyTicket() {
if (!isset($_SESSION['user_id'])) {
header('Location: index.php?controller=Auth&do=showLoginForm');
exit;
}
$event_id = $_POST['event_id'] ?? null;
if (!$event_id) {
$this->view->setVars(['error' => 'Keine Event-ID angegeben.']);
return;
}
$event = $this->eventModel->getEvent($event_id);
if (!$event) {
$this->view->setVars(['error' => 'Event nicht gefunden.']);
return;
}
// Check if user already has a ticket for this event
$hasTicket = $this->ticketModel->hasTicket($_SESSION['user_id'], $event_id);
if ($hasTicket['count'] > 0) {
$this->view->setVars(['error' => 'Sie haben bereits ein Ticket für dieses Event.']);
return;
}
// Calculate valid until date (event end date + 30 days)
$valid_until = date('Y-m-d', strtotime($event['end_date'] . ' +30 days'));
$data = [
'user_id' => $_SESSION['user_id'],
'event_id' => $event_id,
'purchase_date' => date('Y-m-d'),
'valid_until' => $valid_until
];
try {
$ticket_id = $this->ticketModel->buyTicket($data);
$this->view->setVars([
'event' => $event,
'ticket_id' => $ticket_id,
'purchase_date' => $data['purchase_date'],
'valid_until' => $valid_until
]);
$this->view->setDoMethodName('buyTicket');
} catch (Exception $e) {
$this->view->setVars(['error' => 'Fehler beim Kauf des Tickets: ' . $e->getMessage()]);
$this->view->setDoMethodName('showBuyTicketForm');
}
}
public function deleteTicket() {
if (!isset($_SESSION['user_id'])) {
$this->view->setVars(['redirect' => 'index.php?controller=Auth&do=showLoginForm']);
return;
}
$ticket_id = $_GET['ticket_id'] ?? null;
if ($ticket_id) {
$this->ticketModel->deleteTicket($ticket_id);
}
// Redirect to tickets page using JavaScript
$this->view->setVars(['redirect' => 'index.php?controller=Ticket&do=showTickets']);
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Blog\Controller;
class TicketsController {
function showTickets()
{
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace Blog\Controller;
class WelcomeController
{
function showWelcome() {
}
function showProjects() {
}
function showTutorials() {
}
}

240
Model/AuthModel.php Normal file
View File

@ -0,0 +1,240 @@
<?php
namespace Blog\Model;
use DateTime;
use PDO;
use PDOException;
class AuthModel extends Database
{
public function login(string $email, string $password)
{
$pdo = $this->linkDB();
$sql = "SELECT email, password, valid_until, is_admin FROM user WHERE email = :email";
$params = [":email" => $email];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
$user = $sth->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Abrufen der Benutzerdaten.", $e);
return ['success' => false, 'error' => "Interner Datenbankfehler."];
}
if (!$user) {
return ['success' => false, 'error' => "Benutzer mit dieser E-Mail wurde nicht gefunden."];
}
if (!password_verify($password, $user['password'])) {
return ['success' => false, 'error' => "Das eingegebene Passwort ist falsch."];
}
try {
$now = new DateTime();
$validUntil = new DateTime($user['valid_until']);
if ($now > $validUntil) {
return ['success' => false, 'error' => "Ihr Passwort ist abgelaufen. Bitte setzen Sie ein neues über \"Passwort vergessen\"."];
}
} catch (\Exception $e) {
new \Blog\Library\ErrorMsg("Fehler beim Verarbeiten des Gültigkeitsdatums.", $e);
return ['success' => false, 'error' => "Fehler bei der Passwortprüfung."];
}
return ['success' => true, 'user' => $user];
}
public function register($data) {
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
return "Bitte geben Sie eine gültige E-Mail ein.";
}
$requiredFields = [
'email', 'password', 'password_repeat', 'street', 'house_number', 'city', 'postal_code',
'country', 'first_name', 'last_name', 'phone'
];
foreach ($requiredFields as $field) {
if (empty($data[$field])) {
return "Bitte füllen Sie alle Felder aus.";
}
}
if ($this->userExistsByEmail($data['email'])) {
return "Ein Account mit dieser E-Mail existiert bereits.";
}
// Passwort-Validierung
if (!$this->checkDoublePw($data['password'], $data['password_repeat'])) {
return "Passwörter stimmen nicht überein.";
}
$pwCheck = $this->pwRequirementCheck($data['password']);
if ($pwCheck !== true) {
return $pwCheck; // Array mit spezifischen Fehlern zurückgeben
}
$hashedPassword = password_hash($data['password'], PASSWORD_DEFAULT);
$sql = "INSERT INTO user (email, password, street, house_number, city, postal_code, country, first_name, last_name, phone, is_admin)
VALUES (:email, :password, :street, :house_number, :city, :postal_code, :country, :first_name, :last_name, :phone, :is_admin)";
$params = [
':email' => $data['email'],
':password' => $hashedPassword,
':street' => $data['street'],
':house_number' => $data['house_number'],
':city' => $data['city'],
':postal_code'=> $data['postal_code'],
':country'=> $data['country'],
':first_name' => $data['first_name'],
':last_name'=> $data['last_name'],
':phone' => $data['phone'],
':is_admin' => $data['is_admin'] ? 1 : 0,
];
try {
$pdo = $this->linkDB();
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return true;
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Schreiben der Daten.", $e);
return false;
}
}
private function userExistsByEmail($email) {
try {
$pdo = $this->linkDB();
$sql = "SELECT user_id FROM user WHERE email = :email";
$params = [':email' => $email];
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return (bool) $stmt->fetch();
} catch (\PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler bei der E-Mail-Prüfung", $e);
return false;
}
}
public function pwForgot($email){
$randomPw = bin2hex(random_bytes(12 / 2));
$hashedPassword = password_hash($randomPw, PASSWORD_DEFAULT);
$this->forgottenPwUpdate($email, $hashedPassword);
$betreff = "Passwort zurücksetzen bei bibArts";
$nachricht = "Hallo,\n\nhier ihr temporäres Passwort:\n\n $randomPw \n\n Bitte beachten Sie, dass das Passwort nur 2 stunden Gülltig ist. \nViele Grüße,\nbibArts Team";
$header = "From: noreply@edu.bib.de\r\n";
$header .= "Content-Type: text/plain; charset=UTF-8\r\n";
$maxTries = 5;
$try = 0;
$success = false;
while ($try < $maxTries && !$success) {
$erfolg = mail($email, $betreff, $nachricht, $header);
$try++;
if (!$erfolg) {
error_log("Mailversuch $try an $email fehlgeschlagen.");
sleep(1);
}
}
}
private function forgottenPwUpdate($email, $hashedPassword) {
try{
$pdo = $this->linkDB();
$sqlCheck = "SELECT COUNT(*) FROM user WHERE email = :email";
$stmt = $pdo->prepare($sqlCheck);
$stmt->execute([':email' => $email]);
if ($stmt->fetchColumn() == 0) {
return false;
}
$validUntil = (new DateTime())->add(new DateInterval('PT2H'))->format('Y-m-d H:i:s');
$sql = "UPDATE user
SET password = :password, valid_until = :valid_until
WHERE email = :email";
$stmt = $pdo->prepare($sql);
$params = [
':email' => $email,
':password' => $hashedPassword,
':valid_until' => $validUntil
];
return $stmt->execute($params);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Aktualisieren der Daten.", $e);
die;
return false;
}
}
public function updatePassword($email, $oldpw, $newpw){
if(!$this->login($email, $oldpw)) {
return false;
}
$requiredFields = [$email, $oldpw, $newpw];
foreach ($requiredFields as $field) {
if (empty($field)) {
return "Bitte füllen Sie alle Felder aus";
}
}
$hashedPassword = password_hash($newpw, PASSWORD_DEFAULT);
$sql = "UPDATE user SET password = :password WHERE email = :email";
try{
$pdo = $this->linkDB();
$stmt = $pdo->prepare($sql);
$params = [
':email' => $email,
':password' => $hashedPassword,
];
return $stmt->execute($params);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Schreiben der Daten.", $e);
die;
}
}
public function checkDoublePw($password1, $password2){
if($password1 === $password2){
return true;
}
else
return false;
}
public function pwRequirementCheck($password){
$error = [];
if(strlen($password) < 8)
$error[] = "Passwort: mindestens 8 Zeichen";
if(!preg_match("/[A-Z]/", $password))
$error[] = "Passwort: mindestens ein Großbuchstabe";
if(!preg_match("/[a-z]/", $password))
$error[] = "Passwort: mindestens ein Kleinbuchstabe";
if(!preg_match("/[0-9]/", $password))
$error[] = "Passwort: mindestens eine Zahl";
if(!preg_match("/[^a-zA-Z0-9\s]/", $password))
$error[] = "Passwort: mindestens ein Sonderzeichen";
if(empty($error))
return true;
else
return $error;
}
}

View File

@ -1,31 +0,0 @@
<?php
namespace Blog\Model;
use PDOException;
class ContactModel extends Database
{
public function writeContactData($values)
{
$guid = $this->createUUID();
$sql = "INSERT INTO contact (`id`, `name`, `email`, `content`) VALUES (
:guid, :name, :email, :content);";
$pdo = $this->linkDB();
try {
$sth = $pdo->prepare($sql);
$sth->execute(array(":guid" => $guid,
":name" => $values["name"],
":email" => $values["email"],
":content" => $values["content"]));
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Schreiben der Daten.", $e);
die;
}
return true;
}
}

90
Model/EventModel.php Normal file
View File

@ -0,0 +1,90 @@
<?php
namespace Blog\Model;
use PDOException;
class EventModel extends Database {
public function getEvents() {
$pdo = $this->linkDB();
$sql = "SELECT * FROM event ORDER BY start_date DESC;";
try {
$sth = $pdo->prepare($sql);
$sth->execute();
return $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der Events.", $e);
die;
}
}
public function getEvent($id) {
$pdo = $this->linkDB();
$sql = "SELECT * FROM event WHERE event_id = :id;";
try {
$sth = $pdo->prepare($sql);
$sth->execute([":id" => $id]);
return $sth->fetch(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen des Events.", $e);
die;
}
}
public function updateEvent($id, $data) {
$pdo = $this->linkDB();
$sql = "UPDATE event SET location_id = :location_id, start_date = :start_date, end_date = :end_date, name = :name, description = :description, max_tickets = :max_tickets, ticket_price = :ticket_price WHERE event_id = :id;";
$params = [
":location_id" => $data['location_id'],
":start_date" => $data['start_date'],
":end_date" => $data['end_date'],
":name" => $data['name'],
":description" => $data['description'],
":max_tickets" => $data['max_tickets'],
":ticket_price" => $data['ticket_price'],
":id" => $id
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Aktualisieren des Events.", $e);
die;
}
}
public function createEvent($data) {
$pdo = $this->linkDB();
$sql = "INSERT INTO event (location_id, start_date, end_date, name, description, max_tickets, ticket_price) VALUES (:location_id, :start_date, :end_date, :name, :description, :max_tickets, :ticket_price);";
$params = [
":location_id" => $data['location_id'],
":start_date" => $data['start_date'],
":end_date" => $data['end_date'],
":name" => $data['name'],
":description" => $data['description'],
":max_tickets" => $data['max_tickets'],
":ticket_price" => $data['ticket_price']
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth;
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Erstellen des Events.", $e);
die;
}
}
public function deleteEvent($id) {
$pdo = $this->linkDB();
$sql = "DELETE FROM event WHERE event_id = :id;";
try {
$sth = $pdo->prepare($sql);
$sth->execute([":id" => $id]);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Löschen des Events.", $e);
die;
}
}
}

86
Model/GutscheinModel.php Normal file
View File

@ -0,0 +1,86 @@
<?php
namespace Blog\Model;
use PDOException;
class GutscheinModel extends Database {
public function getGutscheine() {
$pdo = $this->linkDB();
$sql = "SELECT * FROM voucher ORDER BY valid_until DESC;";
try {
$sth = $pdo->prepare($sql);
$sth->execute();
return $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der Gutscheine.", $e);
die;
}
}
public function getGutschein($id) {
$pdo = $this->linkDB();
$sql = "SELECT * FROM voucher WHERE voucher_id = :id;";
$params = [":id" => $id];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->fetch(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen des Gutscheins.", $e);
die;
}
}
public function createGutschein($data) {
$pdo = $this->linkDB();
$sql = "INSERT INTO voucher (code, discount, event_id, valid_until) VALUES (:code, :discount, :event_id, :valid_until);";
$params = [
":code" => $data['code'],
":discount" => $data['discount'],
":event_id" => $data['event_id'],
":valid_until" => $data['valid_until']
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth;
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Erstellen des Gutscheins.", $e);
die;
}
}
public function updateGutschein($id, $data) {
$pdo = $this->linkDB();
$sql = "UPDATE voucher SET code = :code, discount = :discount, event_id = :event_id, valid_until = :valid_until WHERE voucher_id = :id;";
$params = [
":code" => $data['code'],
":discount" => $data['discount'],
":event_id" => $data['event_id'],
":valid_until" => $data['valid_until'],
":id" => $id
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Aktualisieren des Gutscheins.", $e);
die;
}
}
public function deleteGutschein($id) {
$pdo = $this->linkDB();
$sql = "DELETE FROM voucher WHERE voucher_id = :id;";
$params = [":id" => $id];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Löschen des Gutscheins.", $e);
die;
}
}
}

85
Model/NewsModel.php Normal file
View File

@ -0,0 +1,85 @@
<?php
namespace Blog\Model;
use PDOException;
class NewsModel extends Database {
public function getNewsById($newsId) {
$pdo = $this->linkDB();
$sql = "SELECT * FROM news WHERE news_id = :news_id;";
$params = [":news_id" => $newsId];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->fetch(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der News.", $e);
die;
}
}
public function updateNews($newsId, $news) {
$pdo = $this->linkDB();
$sql = "UPDATE news SET name = :name, description = :description, date = :date WHERE news_id = :news_id;";
$params = [
":name" => $news['name'],
":description" => $news['description'],
":date" => $news['date'],
":news_id" => $newsId
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth;
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Aktualisieren der News.", $e);
die;
}
}
public function getNews() {
$pdo = $this->linkDB();
$sql = "SELECT * FROM news ORDER BY date DESC;";
try {
$sth = $pdo->prepare($sql);
$sth->execute();
return $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der News.", $e);
die;
}
}
public function createNews($news) {
$pdo = $this->linkDB();
$sql = "INSERT INTO news (name, description, date) VALUES (:name, :description, :date);";
$params = [
":name" => $news['name'],
":description" => $news['description'],
":date" => $news['date']
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth;
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Schreiben der News.", $e);
die;
}
}
public function deleteNews($newsId) {
$pdo = $this->linkDB();
$sql = "DELETE FROM news WHERE news_id = :news_id;";
$params = [":news_id" => $newsId];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Löschen der News.", $e);
die;
}
}
}

103
Model/StandortModel.php Normal file
View File

@ -0,0 +1,103 @@
<?php
namespace Blog\Model;
use PDOException;
class StandortModel extends Database {
public function getStandorte() {
$pdo = $this->linkDB();
$sql = "SELECT * FROM location ORDER BY location_id ASC;";
try {
$sth = $pdo->prepare($sql);
$sth->execute();
return $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der Standorte.", $e);
die;
}
}
public function getStandort($location_id) {
$pdo = $this->linkDB();
$sql = "SELECT * FROM location WHERE location_id = :location_id;";
$params = [":location_id" => $location_id];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->fetch(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen des Standorts.", $e);
die;
}
}
public function createStandort($data) {
$pdo = $this->linkDB();
$sql = "INSERT INTO location (street, house_number, postal_code, city, country, phone, email)
VALUES (:street, :house_number, :postal_code, :city, :country, :phone, :email);";
$params = [
":street" => $data['street'],
":house_number" => $data['house_number'],
":postal_code" => $data['postal_code'],
":city" => $data['city'],
":country" => $data['country'],
":phone" => $data['phone'],
":email" => $data['email']
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $pdo->lastInsertId();
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Anlegen des Standorts.", $e);
die;
}
}
public function updateStandort($location_id, $data) {
$pdo = $this->linkDB();
$sql = "UPDATE location SET
street = :street,
house_number = :house_number,
postal_code = :postal_code,
city = :city,
country = :country,
phone = :phone,
email = :email
WHERE location_id = :location_id;";
$params = [
":street" => $data['street'],
":house_number" => $data['house_number'],
":postal_code" => $data['postal_code'],
":city" => $data['city'],
":country" => $data['country'],
":phone" => $data['phone'],
":email" => $data['email'],
":location_id" => $location_id
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->rowCount();
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Aktualisieren des Standorts.", $e);
die;
}
}
public function deleteStandort($location_id) {
$pdo = $this->linkDB();
$sql = "DELETE FROM location WHERE location_id = :location_id;";
$params = [":location_id" => $location_id];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->rowCount();
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Löschen des Standorts.", $e);
die;
}
}
}

120
Model/TicketModel.php Normal file
View File

@ -0,0 +1,120 @@
<?php
namespace Blog\Model;
use PDOException;
class TicketModel extends Database {
public function getTickets() {
$pdo = $this->linkDB();
$sql = "SELECT t.*, e.name as event_name, e.start_date, e.end_date, e.ticket_price,
l.city as location_city, l.street as location_street, l.house_number as location_house_number
FROM ticket t
JOIN event e ON t.event_id = e.event_id
JOIN location l ON e.location_id = l.location_id
ORDER BY t.purchase_date DESC;";
try {
$sth = $pdo->prepare($sql);
$sth->execute();
return $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der Tickets.", $e);
die;
}
}
public function getUserTickets($user_id) {
$pdo = $this->linkDB();
$sql = "SELECT t.*, e.name as event_name, e.start_date, e.end_date, e.ticket_price,
l.city as location_city, l.street as location_street, l.house_number as location_house_number
FROM ticket t
JOIN event e ON t.event_id = e.event_id
JOIN location l ON e.location_id = l.location_id
WHERE t.user_id = :user_id
ORDER BY t.purchase_date DESC;";
$params = [":user_id" => $user_id];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Lesen der Benutzer-Tickets.", $e);
die;
}
}
public function buyTicket($data) {
$pdo = $this->linkDB();
// First check if the event still has available tickets
$checkSql = "SELECT e.max_tickets, COUNT(t.ticket_id) as sold_tickets
FROM event e
LEFT JOIN ticket t ON e.event_id = t.event_id
WHERE e.event_id = :event_id
GROUP BY e.event_id, e.max_tickets";
try {
$checkStmt = $pdo->prepare($checkSql);
$checkStmt->execute([':event_id' => $data['event_id']]);
$eventInfo = $checkStmt->fetch(\PDO::FETCH_ASSOC);
if (!$eventInfo) {
throw new \Exception("Event nicht gefunden.");
}
if ($eventInfo['sold_tickets'] >= $eventInfo['max_tickets']) {
throw new \Exception("Alle Tickets für dieses Event sind bereits verkauft.");
}
} catch (PDOException $e) {
throw new \Exception("Fehler bei der Ticketverfügbarkeitsprüfung.");
}
$sql = "INSERT INTO ticket (user_id, event_id, purchase_date, valid_until)
VALUES (:user_id, :event_id, :purchase_date, :valid_until);";
$params = [
":user_id" => $data['user_id'],
":event_id" => $data['event_id'],
":purchase_date" => $data['purchase_date'],
":valid_until" => $data['valid_until']
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $pdo->lastInsertId();
} catch (PDOException $e) {
throw new \Exception("Fehler beim Kauf des Tickets.");
}
}
public function hasTicket($user_id, $event_id) {
$pdo = $this->linkDB();
$sql = "SELECT COUNT(*) as count FROM ticket WHERE user_id = :user_id AND event_id = :event_id;";
$params = [
":user_id" => $user_id,
":event_id" => $event_id
];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->fetch(\PDO::FETCH_ASSOC);
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler bei der Ticketprüfung.", $e);
die;
}
}
public function deleteTicket($ticket_id) {
$pdo = $this->linkDB();
$sql = "DELETE FROM ticket WHERE ticket_id = :ticket_id;";
$params = [":ticket_id" => $ticket_id];
try {
$sth = $pdo->prepare($sql);
$sth->execute($params);
return $sth->rowCount();
} catch (PDOException $e) {
new \Blog\Library\ErrorMsg("Fehler beim Löschen des Tickets.", $e);
die;
}
}
}

View File

@ -2,4 +2,4 @@
EIA Projekt
Max stink
Viktor stink

View File

@ -0,0 +1,23 @@
<div class="inhalt">
<div class="form-container">
<h1>Anmelden</h1>
<?php if (!empty($errors['login'])): ?>
<div class="login-error"><?=htmlspecialchars($errors['login'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Auth">
<input type="hidden" name="do" value="login">
<label for="email">E-Mail</label>
<input class="input-email" type="email" name="email" id="email" placeholder="E-Mail" required>
<label for="password">Passwort</label>
<input class="input-passwort" type="password" name="password" id="password" placeholder="Passwort" required>
<button class="button-loggin" type="submit">Login</button>
</form>
<div style="text-align:center; margin-top: 1.5em;">
<a class="link-passwort-vergessen" href="?controller=Auth&do=showForgotPasswordForm">Passwort vergessen?</a>
<br>
<a class="link-konto-erstellen" href="?controller=Auth&do=showRegistrationForm">Konto erstellen</a>
</div>
</div>
</div>

View File

@ -0,0 +1,23 @@
<div class="inhalt">
<div class="form-container">
<h1>Anmelden</h1>
<?php if (!empty($errors['login'])): ?>
<div class="error-box"><?=htmlspecialchars($errors['login'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Auth">
<input type="hidden" name="do" value="login">
<label for="email">E-Mail</label>
<input class="input-email" type="email" name="email" id="email" placeholder="E-Mail" required>
<label for="password">Passwort</label>
<input class="input-passwort" type="password" name="password" id="password" placeholder="Passwort" required>
<button class="button-login" type="submit">Login</button>
</form>
<div style="text-align:center; margin-top: 1.5em;">
<a class="link-passwort-vergessen" href="?controller=Auth&do=showForgotPasswordForm">Passwort vergessen?</a>
<br>
<a class="link-konto-erstellen" href="?controller=Auth&do=showRegistrationForm">Konto erstellen</a>
</div>
</div>
</div>

View File

@ -0,0 +1,15 @@
<div class="inhalt">
<div class="status-box">
<h2>Login erfolgreich!</h2>
<p>Sie werden in wenigen Sekunden zu den News weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=News&do=showNews";
}, 2000); // 2 Sekunden warten
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=News&do=showNews">
</noscript>

View File

@ -0,0 +1,14 @@
<div class="inhalt">
<div class="status-box">
<h2>Logout erfolgreich!</h2>
<p>Sie werden in wenigen Sekunden zum Login weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=Auth&do=showLoginForm";
}, 2000); // 2 Sekunden warten
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=Auth&do=showLoginForm">
</noscript>

View File

@ -0,0 +1,37 @@
<div class="inhalt">
<div class="form-container">
<h1>Registrieren</h1>
<?php if (!empty($errors['register'])): ?>
<div class="error-box"><?=htmlspecialchars($errors['register'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Auth">
<input type="hidden" name="do" value="register">
<label for="first_name">Vorname</label>
<input class="input-vorname" type="text" name="first_name" id="first_name" placeholder="Vorname" required value="<?=htmlspecialchars($validData['first_name'] ?? '')?>">
<label for="last_name">Nachname</label>
<input class="input-nachname" type="text" name="last_name" id="last_name" placeholder="Nachname" required value="<?=htmlspecialchars($validData['last_name'] ?? '')?>">
<label for="email">E-Mail</label>
<input class="input-email" type="email" name="email" id="email" placeholder="E-Mail" required value="<?=htmlspecialchars($validData['email'] ?? '')?>">
<label for="password">Passwort</label>
<input class="input-passwort" type="password" name="password" id="password" placeholder="Passwort" required>
<label for="password_repeat">Passwort wiederholen</label>
<input class="input-passwort-repeat" type="password" name="password_repeat" id="password_repeat" placeholder="Passwort wiederholen" required>
<label for="street">Straße</label>
<input class="input-strasse" type="text" name="street" id="street" placeholder="Straße" required value="<?=htmlspecialchars($validData['street'] ?? '')?>">
<label for="house_number">Hausnr.</label>
<input class="input-hausnr" type="text" name="house_number" id="house_number" placeholder="Hausnr." required value="<?=htmlspecialchars($validData['house_number'] ?? '')?>">
<label for="postal_code">Postleitzahl</label>
<input class="input-postleitzahl" type="text" name="postal_code" id="postal_code" placeholder="Postleitzahl" required value="<?=htmlspecialchars($validData['postal_code'] ?? '')?>">
<label for="city">Ort</label>
<input class="input-ort" type="text" name="city" id="city" placeholder="Ort" required value="<?=htmlspecialchars($validData['city'] ?? '')?>">
<label for="country">Land</label>
<input class="input-land" type="text" name="country" id="country" placeholder="Land" required value="<?=htmlspecialchars($validData['country'] ?? '')?>">
<label for="phone">Telefonnr.</label>
<input class="input-tel" type="text" name="phone" id="phone" placeholder="Telefonnr." required value="<?=htmlspecialchars($validData['phone'] ?? '')?>">
<button class="button-register" type="submit">Registrieren</button>
</form>
<a class="link-konto-erstellen" href="?controller=Auth&do=showLoginForm">Login</a>
</div>
</div>

View File

@ -0,0 +1,14 @@
<div class="inhalt">
<div class="status-box">
<h2>Registrierung erfolgreich!</h2>
<p>Sie werden in wenigen Sekunden zum Login weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=Auth&do=showLoginForm";
}, 2000);
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=Auth&do=showLoginForm">
</noscript>

View File

@ -1,12 +0,0 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<div class="msg">
<p>Ihre Anfrage wurde erfolgreich versendet.</p>
<a href="?controller=Welcome&do=showWelcome">Weiter</a>
</div>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

View File

@ -1,36 +0,0 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<h2>Ihre Anfrage an uns</h2>
<form method="post">
<?php foreach ($labels as $index => $value) {
echo '<label for="' . $index . '">' . $value . '</label>';
if ($index == "content") {
echo "<textarea id=\"$index\" name=\"$index\" >";
if (isset($validData[$index])) { echo $validData[$index]; }
echo "</textarea><br>";
} else {
echo '<input type="text" name="' . $index . '" value="' . (isset($validData[$index]) ? $validData[$index] : '') . '"><br>';
}
if (isset($errors[$index])) {
echo '<label class="errorMsg">' . $errors[$index] . '</label><br>';
}
}
?>
<input type="hidden" name="controller" value="contact">
<input type="hidden" name="do" value="validateForm">
<input type="submit" name="submit" value="Absenden"></form>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

View File

@ -0,0 +1,15 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<div class="inhalt">
<div class="msg">
<p>Das Event mit der ID "<?php echo htmlspecialchars($id); ?>" wurde erfolgreich gelöscht!</p>
<p>Sie werden in 3 Sekunden zur Event-Übersicht weitergeleitet...</p>
<a href="?controller=Event&do=showEvents">Jetzt zur Event-Übersicht</a>
</div>
</div>
<meta http-equiv="refresh" content="3;url=index.php?controller=Event&do=showEvents">
<?php include dirname(__DIR__).'/footer.phtml'; ?>

View File

@ -0,0 +1,38 @@
<div class="inhalt">
<div class="form-container">
<h1>Event erstellen</h1>
<?php if (!empty(
$errors['event'])): ?>
<div class="error-box"><?=htmlspecialchars($errors['event'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Event">
<input type="hidden" name="do" value="createEvent">
<label for="name">Name</label>
<input type="text" name="name" id="name" required value="<?=htmlspecialchars($validData['name'] ?? '')?>">
<label for="start_date">Startdatum</label>
<input type="date" name="start_date" id="start_date" required value="<?=htmlspecialchars($validData['start_date'] ?? '')?>">
<label for="end_date">Enddatum</label>
<input type="date" name="end_date" id="end_date" required value="<?=htmlspecialchars($validData['end_date'] ?? '')?>">
<label for="location_id">Standort</label>
<select name="location_id" id="location_id" required>
<option value="">Standort wählen</option>
<?php if (!empty($locations)): ?>
<?php foreach ($locations as $loc): ?>
<option value="<?= htmlspecialchars($loc['location_id']) ?>" <?= (isset($validData['location_id']) && $validData['location_id'] == $loc['location_id']) ? 'selected' : '' ?>>
<?= htmlspecialchars($loc['city']) ?>, <?= htmlspecialchars($loc['street']) ?> <?= htmlspecialchars($loc['house_number']) ?>
</option>
<?php endforeach; ?>
<?php endif; ?>
</select>
<label for="description">Beschreibung</label>
<textarea name="description" id="description" rows="7" required><?=htmlspecialchars($validData['description'] ?? '')?></textarea>
<label for="max_tickets">Max. Tickets</label>
<input type="number" name="max_tickets" id="max_tickets" required value="<?=htmlspecialchars($validData['max_tickets'] ?? '')?>">
<label for="ticket_price">Ticketpreis</label>
<input type="number" step="0.01" name="ticket_price" id="ticket_price" required value="<?=htmlspecialchars($validData['ticket_price'] ?? '')?>">
<button class="button-register" type="submit">Event erstellen</button>
</form>
<a href="?controller=Event&do=showEvents">Zurück zur Übersicht</a>
</div>
</div>

View File

@ -0,0 +1,15 @@
<div class="inhalt">
<div class="create-forwarding">
<h2>Erstellen...</h2>
<p>Sie werden in wenigen Sekunden zu der Erstell Seite weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=Event&do=showCreateEvent";
}, 2000); // 2 Sekunden warten
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=Event&do=showCreateEvent">
</noscript>

View File

@ -0,0 +1,74 @@
<?php if (!empty($events)): ?>
<div class="inhalt">
<div class="content-container">
<div class="event-header">
<h2>Alle Ausstellungen</h2>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<a href="?controller=Event&do=showCreateEvent" class="admin-btn">Event erstellen</a>
<?php endif; ?>
</div>
<div class="event-container-inhalt">
<table>
<thead>
<tr>
<th>Name</th>
<th>Beschreibung</th>
<th>Von</th>
<th>Bis</th>
<th>Preis</th>
<th>Tickets</th>
<th>Aktionen</th>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<th>Admin</th>
<?php endif; ?>
</tr>
</thead>
<tbody>
<?php foreach ($events as $event): ?>
<tr class="event-row" data-event-id="<?php echo $event['event_id']; ?>" style="cursor: pointer;">
<td><?php echo htmlspecialchars($event['name']); ?></td>
<td><?php echo nl2br(htmlspecialchars($event['description'])); ?></td>
<td><?php echo date('d.m.Y', strtotime($event['start_date'])); ?></td>
<td><?php echo date('d.m.Y', strtotime($event['end_date'])); ?></td>
<td><?php echo number_format($event['ticket_price'], 2, ',', '.'); ?></td>
<td><?php echo (int) $event['max_tickets']; ?></td>
<td>
<a href="?controller=Ticket&do=showBuyTicketForm&event_id=<?php echo $event['event_id']; ?>" class="admin-btn">Ticket kaufen</a>
</td>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<td>
<a href="?controller=Event&do=showUpdateEvent&event_id=<?php echo $event['event_id']; ?>" class="admin-btn">Bearbeiten</a>
<a href="?controller=Event&do=deleteEvent&event_id=<?php echo $event['event_id']; ?>" class="admin-btn" onclick="return confirm('Wirklich löschen?');">Löschen</a>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const eventRows = document.querySelectorAll('.event-row');
eventRows.forEach(function(row) {
row.addEventListener('dblclick', function(e) {
// Don't trigger if clicking on a link or button
if (e.target.tagName === 'A' || e.target.tagName === 'BUTTON') {
return;
}
const eventId = this.getAttribute('data-event-id');
if (eventId) {
window.location.href = 'index.php?controller=Ticket&do=showBuyTicketForm&event_id=' + eventId;
}
});
});
});
</script>
<?php else: ?>
<p>Derzeit sind keine Ausstellungen verfügbar.</p>
<?php endif; ?>

View File

@ -0,0 +1,31 @@
<div class="inhalt">
<div class="form-container">
<h1>Event bearbeiten</h1>
<?php if (!empty(
$errors['event'])): ?>
<div class="error-box"><?=htmlspecialchars($errors['event'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Event">
<input type="hidden" name="do" value="updateEvent">
<input type="hidden" name="id" value="<?=htmlspecialchars($event['id'] ?? '')?>">
<label for="name">Name</label>
<input type="text" name="name" id="name" required value="<?=htmlspecialchars($event['name'] ?? '')?>">
<label for="start_date">Startdatum</label>
<input type="date" name="start_date" id="start_date" required value="<?=htmlspecialchars($event['start_date'] ?? '')?>">
<label for="end_date">Enddatum</label>
<input type="date" name="end_date" id="end_date" required value="<?=htmlspecialchars($event['end_date'] ?? '')?>">
<label for="location_id">Standort</label>
<input type="text" name="location_name" value="<?=htmlspecialchars($event['location_name'] ?? '')?>" readonly>
<input type="hidden" name="location_id" value="<?=htmlspecialchars($event['location_id'] ?? '')?>">
<label for="description">Beschreibung</label>
<textarea name="description" id="description" rows="7" required><?=htmlspecialchars($event['description'] ?? '')?></textarea>
<label for="max_tickets">Max. Tickets</label>
<input type="number" name="max_tickets" id="max_tickets" required value="<?=htmlspecialchars($event['max_tickets'] ?? '')?>">
<label for="ticket_price">Ticketpreis</label>
<input type="number" step="0.01" name="ticket_price" id="ticket_price" required value="<?=htmlspecialchars($event['ticket_price'] ?? '')?>">
<button class="button-register" type="submit">Änderungen speichern</button>
</form>
<a href="?controller=Event&do=showEvents">Zurück zur Übersicht</a>
</div>
</div>

View File

@ -0,0 +1,15 @@
<div class="inhalt">
<div class="update-forwarding">
<h2>Editieren...</h2>
<p>Sie werden in wenigen Sekunden zur Edit Seite weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=Event&do=showUpdateEvent";
}, 2000); // 2 Sekunden warten
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=Event&do=showUpdateEvent">
</noscript>

View File

@ -0,0 +1 @@
echo "create gutschein"

View File

@ -0,0 +1,19 @@
<div class="inhalt">
<div class="form-container">
<h1>Neuen Gutschein anlegen</h1>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Gutschein">
<input type="hidden" name="do" value="createGutschein">
<label for="code">Code</label>
<input type="text" id="code" name="code" required>
<label for="discount">Rabatt (%)</label>
<input type="number" id="discount" name="discount" min="0" max="100" required>
<label for="event_id">Event-ID</label>
<input type="number" id="event_id" name="event_id" required>
<label for="valid_until">Gültig bis</label>
<input type="date" id="valid_until" name="valid_until" required>
<button class="admin-btn" type="submit">Erstellen</button>
</form>
<a href="?controller=Gutschein&do=adminVerwaltung" class="admin-btn" style="background:#888;">Abbrechen</a>
</div>
</div>

View File

@ -0,0 +1,20 @@
<div class="inhalt">
<div class="form-container">
<h1>Gutschein bearbeiten</h1>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Gutschein">
<input type="hidden" name="do" value="updateGutschein">
<input type="hidden" name="gutscheinid" value="<?=htmlspecialchars($gutschein['voucher_id'])?>">
<label for="code">Code</label>
<input type="text" id="code" name="code" required value="<?=htmlspecialchars($gutschein['code'])?>">
<label for="discount">Rabatt (%)</label>
<input type="number" id="discount" name="discount" min="0" max="100" required value="<?=htmlspecialchars($gutschein['discount'])?>">
<label for="event_id">Event-ID</label>
<input type="number" id="event_id" name="event_id" required value="<?=htmlspecialchars($gutschein['event_id'])?>">
<label for="valid_until">Gültig bis</label>
<input type="date" id="valid_until" name="valid_until" required value="<?=htmlspecialchars($gutschein['valid_until'])?>">
<button class="admin-btn" type="submit">Speichern</button>
</form>
<a href="?controller=Gutschein&do=adminVerwaltung" class="admin-btn" style="background:#888;">Abbrechen</a>
</div>
</div>

View File

@ -0,0 +1,14 @@
<div class="inhalt">
<div class="status-box">
<h2>Gutschein erfolgreich erstellt!</h2>
<p>Du wirst in wenigen Sekunden zur Übersicht weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=Gutschein&do=adminVerwaltung";
}, 2000);
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=Gutschein&do=adminVerwaltung">
</noscript>

View File

@ -0,0 +1,35 @@
<div class="inhalt" style="flex-direction:column;align-items:center;">
<div class="gutschein-header-block">
<h2>Alle Gutscheine</h2>
<a href="?controller=Gutschein&do=createGutscheinForm" class="admin-btn">Neuen Gutschein anlegen</a>
</div>
<?php if (!empty($gutscheine)): ?>
<table class="gutschein-table">
<thead>
<tr>
<th>Code</th>
<th>Rabatt (%)</th>
<th>Event-ID</th>
<th>Gültig bis</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php foreach ($gutscheine as $g): ?>
<tr>
<td><?php echo htmlspecialchars($g['code']); ?></td>
<td><?php echo (int)$g['discount']; ?></td>
<td><?php echo (int)$g['event_id']; ?></td>
<td><?php echo htmlspecialchars($g['valid_until']); ?></td>
<td>
<a href="?controller=Gutschein&do=editGutscheinForm&gutscheinid=<?php echo $g['voucher_id']; ?>" class="admin-btn">Bearbeiten</a>
<a href="?controller=Gutschein&do=deleteGutschein&gutscheinid=<?php echo $g['voucher_id']; ?>" class="admin-btn" onclick="return confirm('Wirklich löschen?');">Löschen</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>Keine Gutscheine vorhanden.</p>
<?php endif; ?>
</div>

View File

@ -0,0 +1,20 @@
<div class="inhalt">
<div class="form-container">
<h1>News erstellen</h1>
<?php if (!empty($errors['news'])): ?>
<div class="error-box"><?=htmlspecialchars($errors['news'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="News">
<input type="hidden" name="do" value="createNews">
<label for="name">Titel</label>
<input type="text" name="name" id="name" required value="<?=htmlspecialchars($validData['name'] ?? '')?>">
<label for="date">Datum</label>
<input type="date" name="date" id="date" required value="<?=htmlspecialchars($validData['date'] ?? date('Y-m-d'))?>">
<label for="description">Beschreibung</label>
<textarea name="description" id="description" rows="7" required><?=htmlspecialchars($validData['description'] ?? '')?></textarea>
<button class="button-register" type="submit">News speichern</button>
</form>
<a href="?controller=News&do=showNews">Zurück zur Übersicht</a>
</div>
</div>

View File

@ -0,0 +1,21 @@
<div class="inhalt">
<div class="form-container">
<h1>News bearbeiten</h1>
<?php if (!empty($errors['news'])): ?>
<div class="error-box"><?=htmlspecialchars($errors['news'])?></div>
<?php endif; ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="News">
<input type="hidden" name="do" value="updateNews">
<input type="hidden" name="id" value="<?=htmlspecialchars($id ?? '')?>">
<label for="name">Titel</label>
<input type="text" name="name" id="name" required value="<?=htmlspecialchars($validData['name'] ?? '')?>">
<label for="date">Datum</label>
<input type="date" name="date" id="date" required value="<?=htmlspecialchars($validData['date'] ?? date('Y-m-d'))?>">
<label for="description">Beschreibung</label>
<textarea name="description" id="description" rows="7" required><?=htmlspecialchars($validData['description'] ?? '')?></textarea>
<button class="button-register" type="submit">Änderungen speichern</button>
</form>
<a href="?controller=News&do=showNews">Zurück zur Übersicht</a>
</div>
</div>

View File

@ -0,0 +1,14 @@
<div class="inhalt">
<div class="status-box">
<h2>News erfolgreich erstellt!</h2>
<p>Du wirst in wenigen Sekunden zur Übersicht weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=News&do=showNews";
}, 2000);
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=News&do=showNews">
</noscript>

View File

@ -0,0 +1,14 @@
<div class="inhalt">
<div class="status-box">
<h2>News erfolgreich gelöscht!</h2>
<p>Du wirst in wenigen Sekunden zur Übersicht weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=News&do=showNews";
}, 2000);
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=News&do=showNews">
</noscript>

View File

@ -0,0 +1,14 @@
<div class="inhalt">
<div class="status-box">
<h2>News erfolgreich bearbeitet!</h2>
<p>Du wirst in wenigen Sekunden zur Übersicht weitergeleitet...</p>
</div>
</div>
<script>
setTimeout(function() {
window.location.href = "?controller=News&do=showNews";
}, 2000);
</script>
<noscript>
<meta http-equiv="refresh" content="2;url=?controller=News&do=showNews">
</noscript>

40
Views/News/showNews.phtml Normal file
View File

@ -0,0 +1,40 @@
<?php if (!empty($news)): ?>
<div class="inhalt">
<div class="content-container">
<div class="news-header">
<h2>Alle Infos</h2>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<a href="?controller=News&do=createNewsForm" class="admin-btn">News erstellen</a>
<?php endif; ?>
</div>
<div class="news-cards">
<?php foreach ($news as $item): ?>
<div class="card">
<h3><?=htmlspecialchars($item['name'])?></h3>
<div class="news-date"><?=date('d.m.Y', strtotime($item['date']))?></div>
<div class="news-desc">
<?php
$desc = htmlspecialchars($item['description']);
if (mb_strlen($desc) > 255) {
$short = mb_substr($desc, 0, 255) . '...';
echo nl2br($short) . ' <a href="?controller=News&do=showNewsDetail&id=' . $item['news_id'] . '">mehr lesen</a>';
} else {
echo nl2br($desc);
}
?>
</div>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<div class="news-card-actions">
<a href="?controller=News&do=editNewsForm&id=<?=$item['news_id']?>" class="admin-btn">Bearbeiten</a>
<a href="?controller=News&do=deleteNews&id=<?=$item['news_id']?>" class="admin-btn" onclick="return confirm('Wirklich löschen?');">Löschen</a>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p>Derzeit sind keine News verfügbar.</p>
<?php endif; ?>
</div>
</div>
</div>

View File

@ -0,0 +1,10 @@
<div class="inhalt">
<div class="content-container">
<div class="card card--wide">
<h2><?=htmlspecialchars($news['name'])?></h2>
<div class="news-date"><?=date('d.m.Y', strtotime($news['date']))?></div>
<div class="news-desc"><?=nl2br(htmlspecialchars($news['description']))?></div>
<a href="?controller=News&do=showNews" class="admin-btn">Zurück zur Übersicht</a>
</div>
</div>
</div>

View File

View File

@ -0,0 +1,37 @@
<?php include dirname(__DIR__) . '/header.phtml'; ?>
<div class="inhalt">
<h2>Unsere Standorte</h2>
<?php if (!empty($standorte)): ?>
<table border="1" cellpadding="8" cellspacing="0">
<thead>
<tr>
<th>Straße</th>
<th>Hausnr.</th>
<th>PLZ</th>
<th>Ort</th>
<th>Land</th>
<th>Telefon</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<?php foreach ($standorte as $standort): ?>
<tr>
<td><?php echo htmlspecialchars($standort['street']); ?></td>
<td><?php echo htmlspecialchars($standort['house_number']); ?></td>
<td><?php echo htmlspecialchars($standort['postal_code']); ?></td>
<td><?php echo htmlspecialchars($standort['city']); ?></td>
<td><?php echo htmlspecialchars($standort['country']); ?></td>
<td><?php echo htmlspecialchars($standort['phone']); ?></td>
<td><?php echo htmlspecialchars($standort['email']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>Keine Standorte gefunden.</p>
<?php endif; ?>
</div>
<?php include dirname(__DIR__) . '/footer.phtml'; ?>

View File

@ -0,0 +1,27 @@
<div class="inhalt">
<div class="form-container">
<h1>Ticket erfolgreich gekauft!</h1>
<?php if (isset($event) && isset($ticket_id)): ?>
<div class="status-box">
<h2><?= htmlspecialchars($event['name']) ?></h2>
<p><strong>Ticket-ID:</strong> #<?= $ticket_id ?></p>
<p><strong>Kaufdatum:</strong> <?= date('d.m.Y', strtotime($purchase_date)) ?></p>
<p><strong>Gültig bis:</strong> <?= date('d.m.Y', strtotime($valid_until)) ?></p>
<p><strong>Preis:</strong> <?= number_format($event['ticket_price'], 2, ',', '.') ?></p>
<p><strong>Datum:</strong> <?= date('d.m.Y', strtotime($event['start_date'])) ?> - <?= date('d.m.Y', strtotime($event['end_date'])) ?></p>
</div>
<div style="text-align:center; margin-top: 1.5em;">
<a href="?controller=Ticket&do=showTickets" class="admin-btn">Meine Tickets anzeigen</a>
<br><br>
<a href="?controller=Event&do=showEvents">Zurück zu den Events</a>
</div>
<?php else: ?>
<div class="error-box">Fehler beim Anzeigen der Ticket-Details.</div>
<div style="text-align:center; margin-top: 1.5em;">
<a href="?controller=Event&do=showEvents">Zurück zu den Events</a>
</div>
<?php endif; ?>
</div>
</div>

View File

@ -0,0 +1,48 @@
<div class="inhalt">
<div class="form-container">
<h1>Ticket kaufen</h1>
<?php if (isset($event)): ?>
<div class="event-details">
<h2><?= htmlspecialchars($event['name']) ?></h2>
<p><strong>Beschreibung:</strong> <?= nl2br(htmlspecialchars($event['description'])) ?></p>
<p><strong>Datum:</strong> <?= date('d.m.Y', strtotime($event['start_date'])) ?> - <?= date('d.m.Y', strtotime($event['end_date'])) ?></p>
<p><strong>Preis:</strong> <?= number_format($event['ticket_price'], 2, ',', '.') ?></p>
<p><strong>Max. Tickets:</strong> <?= (int) $event['max_tickets'] ?></p>
</div>
<?php if ($hasTicket): ?>
<div class="status-box">
<p>Sie haben bereits ein Ticket für dieses Event gekauft.</p>
<a href="?controller=Ticket&do=showTickets" class="admin-btn">Meine Tickets anzeigen</a>
</div>
<?php else: ?>
<form class="form-horizontal" action="index.php" method="post">
<input type="hidden" name="controller" value="Ticket">
<input type="hidden" name="do" value="buyTicket">
<input type="hidden" name="event_id" value="<?= $event['event_id'] ?>">
<p>Möchten Sie ein Ticket für dieses Event kaufen?</p>
<p><strong>Preis:</strong> <?= number_format($event['ticket_price'], 2, ',', '.') ?></p>
<button class="button-login" type="submit">Jetzt kaufen</button>
</form>
<div style="text-align:center; margin-top: 1.5em;">
<a href="?controller=Event&do=showEvents">Zurück zu den Events</a>
</div>
<?php endif; ?>
<?php else: ?>
<div class="error-box">Event nicht gefunden.</div>
<div style="text-align:center; margin-top: 1.5em;">
<a href="?controller=Event&do=showEvents">Zurück zu den Events</a>
</div>
<?php endif; ?>
</div>
</div>
<?php if (isset($redirect)): ?>
<script>
window.location.href = '<?= $redirect ?>';
</script>
<?php endif; ?>

View File

@ -0,0 +1,53 @@
<div class="inhalt">
<div class="content-container">
<div class="event-header">
<h2>Meine Tickets</h2>
</div>
<?php if (!empty($tickets)): ?>
<div class="event-container-inhalt">
<table>
<thead>
<tr>
<th>Event</th>
<th>Datum</th>
<th>Standort</th>
<th>Preis</th>
<th>Kaufdatum</th>
<th>Gültig bis</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php foreach ($tickets as $ticket): ?>
<tr>
<td><?= htmlspecialchars($ticket['event_name']) ?></td>
<td><?= date('d.m.Y', strtotime($ticket['start_date'])) ?> - <?= date('d.m.Y', strtotime($ticket['end_date'])) ?></td>
<td><?= htmlspecialchars($ticket['location_street'] . ' ' . $ticket['location_house_number'] . ', ' . $ticket['location_city']) ?></td>
<td><?= number_format($ticket['ticket_price'], 2, ',', '.') ?></td>
<td><?= date('d.m.Y', strtotime($ticket['purchase_date'])) ?></td>
<td><?= date('d.m.Y', strtotime($ticket['valid_until'])) ?></td>
<td>
<a href="?controller=Ticket&do=deleteTicket&ticket_id=<?= $ticket['ticket_id'] ?>"
class="admin-btn"
onclick="return confirm('Ticket wirklich löschen?')">Löschen</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php else: ?>
<div class="status-box">
<p>Sie haben noch keine Tickets gekauft.</p>
<a href="?controller=Event&do=showEvents" class="admin-btn">Events anzeigen</a>
</div>
<?php endif; ?>
</div>
</div>
<?php if (isset($redirect)): ?>
<script>
window.location.href = '<?= $redirect ?>';
</script>
<?php endif; ?>

View File

@ -1,21 +0,0 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<article>
<h2>Virtuelles Museum</h2>
<span class="articleInfo">John Doe | 12.08.2018 um 10:18 Uhr</span>
<p>
<img class="articleImg" src="images/museum.jpg" alt="my Oculus Rift">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Curabitur pretium tincidunt lacus. Nulla gravida orci a odio.
</p>
<p>
Proin nonummy, lacus eget pulvinar lacinia, pede felis dignissim leo, vitae tristique magna lacus sit amet eros. Nullam ornare. Praesent odio ligula, dapibus sed, tincidunt eget, dictum ac, nibh. Nam quis lacus. Nunc eleifend molestie velit. Morbi lobortis quam eu velit. Donec euismod vestibulum massa. Donec non lectus. Aliquam commodo lacus sit amet nulla. Cras dignissim elit et augue. Nullam non diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Aenean vestibulum. Sed lobortis elit quis lectus. Nunc sed lacus at augue bibendum dapibus.
</p>
<p>
Aliquam vehicula sem ut pede. Cras purus lectus, egestas eu, vehicula at, imperdiet sed, nibh. Morbi consectetuer luctus felis. Donec vitae nisi. Aliquam tincidunt feugiat elit. Duis sed elit ut turpis ullamcorper feugiat. Praesent pretium, mauris sed fermentum hendrerit, nulla lorem iaculis magna, pulvinar scelerisque urna tellus a justo. Suspendisse pulvinar massa in metus. Duis quis quam. Proin justo. Curabitur ac sapien. Nam erat.
Praesent ut quam.
</p>
</article>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

View File

@ -1,21 +0,0 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<article>
<h2>Implement Controller</h2>
<span class="articleInfo">John Doe | 18.07.2018 um 18:43 Uhr</span>
<p>
<img class="articleImg" src="images/controller.jpg" alt="my Oculus Rift">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Curabitur pretium tincidunt lacus. Nulla gravida orci a odio.
</p>
<p>
Proin nonummy, lacus eget pulvinar lacinia, pede felis dignissim leo, vitae tristique magna lacus sit amet eros. Nullam ornare. Praesent odio ligula, dapibus sed, tincidunt eget, dictum ac, nibh. Nam quis lacus. Nunc eleifend molestie velit. Morbi lobortis quam eu velit. Donec euismod vestibulum massa. Donec non lectus. Aliquam commodo lacus sit amet nulla. Cras dignissim elit et augue. Nullam non diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Aenean vestibulum. Sed lobortis elit quis lectus. Nunc sed lacus at augue bibendum dapibus.
</p>
<p>
Aliquam vehicula sem ut pede. Cras purus lectus, egestas eu, vehicula at, imperdiet sed, nibh. Morbi consectetuer luctus felis. Donec vitae nisi. Aliquam tincidunt feugiat elit. Duis sed elit ut turpis ullamcorper feugiat. Praesent pretium, mauris sed fermentum hendrerit, nulla lorem iaculis magna, pulvinar scelerisque urna tellus a justo. Suspendisse pulvinar massa in metus. Duis quis quam. Proin justo. Curabitur ac sapien. Nam erat.
Praesent ut quam.
</p>
</article>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

View File

@ -1,23 +0,0 @@
<?php
include dirname(__DIR__).'/header.phtml';
?>
<!-- <a href="?controller=guestbook&do=showGuestbookForm">Neuen Eintrag schreiben</a> -->
<article>
<h2>Willkommen</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, molestie eu, feugiat in, orci. In hac habitasse platea dictumst.
</p>
<p>
Fusce convallis, mauris imperdiet gravida bibendum, nisl turpis suscipit mauris, sed placerat ipsum urna sed risus. In convallis tellus a mauris. Curabitur non elit ut libero tristique sodales. Mauris a lacus. Donec mattis semper leo. In hac habitasse platea dictumst. Vivamus facilisis diam at odio. Mauris dictum, nisi eget consequat elementum, lacus ligula molestie metus, non feugiat orci magna ac sem. Donec turpis. Donec vitae metus. Morbi tristique neque eu mauris. Quisque gravida ipsum non sapien. Proin turpis lacus, scelerisque vitae, elementum at, lobortis ac, quam. Aliquam dictum eleifend risus. In hac habitasse platea dictumst. Etiam sit amet diam. Suspendisse odio. Suspendisse nunc. In semper bibendum libero.
</p>
<p>
Proin nonummy, lacus eget pulvinar lacinia, pede felis dignissim leo, vitae tristique magna lacus sit amet eros. Nullam ornare. Praesent odio ligula, dapibus sed, tincidunt eget, dictum ac, nibh. Nam quis lacus. Nunc eleifend molestie velit. Morbi lobortis quam eu velit. Donec euismod vestibulum massa. Donec non lectus. Aliquam commodo lacus sit amet nulla. Cras dignissim elit et augue. Nullam non diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Aenean vestibulum. Sed lobortis elit quis lectus.
Nunc sed lacus at augue bibendum dapibus.
</p>
</article>
<?php include dirname(__DIR__).'/footer.phtml'; ?>

View File

@ -1,5 +1,13 @@
</main>
<div id="footer">
<div class="container-zahlungsmittel">
<h2 class="header-zahlungsarten">Mögliche Zahlungsarten</h2>
<div class="zahlungsmittel-img"></div>
</div>
<div class="line"></div>
<a class="link-impressum">Impressum</a>
<a class="link-datenschutz">Datenschutz</a>
<a class="link-nutzungsbedingungen">Nutzungsbedingungen</a>
<span class="text-bib">© bib arts GmbH</span>
</div>
</body>
</html>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<html lang="HTML-5">
<head>
<title>VR Contact</title>
<meta charset="UTF-8" />
@ -7,19 +7,37 @@
<link href="CSS/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="wrapper">
<nav>
<div id="metanavi">
<a href="#">Anmelden</a>
<nav id="navigation">
<div class="link-container">
<div id="logo" ><a class="link-logo" href="#"></a></div>
<button id="nav-toggle-btn" aria-label="Menü ein-/ausklappen">&#9660;</button>
<div class="nav-links">
<?php if (isset($_SESSION['user'])): ?>
<a id="link-tickets" class="links" href="?controller=Event&do=showEvents">Event</a>
<a id="link-infos" class="links" href="?controller=News&do=showNews">Infos</a>
<a id="link-tickets" class="links" href="?controller=Tickets&do=showTickets">Tickets</a>
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
<a id="link-gutscheinverwaltung" class="links" href="?controller=Gutschein&do=adminVerwaltung">Gutscheine</a>
<?php endif; ?>
<a id="link-logout" class="links" href="?controller=Auth&do=logout">Logout</a>
<?php else: ?>
<a id="link-login" class="links" href="?controller=Auth&do=showLoginForm">Login</a>
<a id="link-register" class="links" href="?controller=Auth&do=showRegistrationForm">Register</a>
<?php endif; ?>
<div id="profile-picture"></div>
</div>
</div>
<h1><span>V</span>irtual <span>R</span>evolution</h1>
<ul>
<li><a href="?controller=Welcome&do=showWelcome">Willkommen</a></li>
<li><a href="#">Projekte</a></li>
<li><a href="#">Workshops</a></li>
<li><a href="?controller=Contact&do=showContactForm">Kontakt</a></li>
</ul>
</nav>
<main>
<script>
document.addEventListener('DOMContentLoaded', function() {
var btn = document.getElementById('nav-toggle-btn');
var links = document.querySelector('.nav-links');
if (btn && links) {
btn.addEventListener('click', function() {
links.classList.toggle('open');
btn.classList.toggle('open');
btn.innerHTML = links.classList.contains('open') ? '&#9650;' : '&#9660;';
});
}
});
</script>

131
bibarts.sql Normal file
View File

@ -0,0 +1,131 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
-- --------------------------------------------------------
CREATE TABLE user (
user_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
street VARCHAR(100),
house_number VARCHAR(10),
postal_code VARCHAR(10),
city VARCHAR(50),
country VARCHAR(50),
phone VARCHAR(20),
email VARCHAR(100) UNIQUE,
is_admin BOOLEAN DEFAULT FALSE,
valid_until DATETIME NOT NULL DEFAULT '3025-01-01 00:00:00',
password VARCHAR(255)
);
CREATE TABLE location (
location_id INT AUTO_INCREMENT PRIMARY KEY,
street VARCHAR(100),
house_number VARCHAR(10),
postal_code VARCHAR(10),
city VARCHAR(50),
country VARCHAR(50),
phone VARCHAR(20),
email VARCHAR(100)
);
CREATE TABLE event (
event_id INT AUTO_INCREMENT PRIMARY KEY,
location_id INT,
start_date DATE,
end_date DATE,
name VARCHAR(100),
description TEXT,
max_tickets INT,
ticket_price DECIMAL(5,2),
FOREIGN KEY (location_id) REFERENCES location(location_id)
);
CREATE TABLE ticket (
ticket_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
event_id INT,
purchase_date DATE,
valid_until DATE,
FOREIGN KEY (user_id) REFERENCES user(user_id),
FOREIGN KEY (event_id) REFERENCES event(event_id)
);
CREATE TABLE voucher (
voucher_id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(50) UNIQUE,
discount INT CHECK (discount BETWEEN 0 AND 100),
event_id INT,
valid_until DATE,
FOREIGN KEY (event_id) REFERENCES event(event_id)
);
CREATE TABLE news (
news_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
description TEXT,
date DATE
);
-- User-Daten (Passwort: passwort123)
INSERT INTO user (first_name, last_name, street, house_number, postal_code, city, country, phone, email, is_admin, password)
VALUES
('Max', 'Muster', 'Musterstraße', '1', '12345', 'Musterstadt', 'Deutschland', '0123456789', 'max@muster.de', FALSE, '$2y$10$VAj.C0XHPUxV4oXS6b79aumlg5fBMPPx5FPqgkQSIQeBLh0WtYmKy'),
('Anna', 'Beispiel', 'Beispielweg', '5a', '54321', 'Beispielstadt', 'Deutschland', '0987654321', 'anna@beispiel.de', TRUE, '$2y$10$cnPBpkvLbdpDxzYvxlQg9uVp5y8ggr2SWL8NAMg9zk.3QnnEl.MGq');
-- Standort-Daten
INSERT INTO location (street, house_number, postal_code, city, country, phone, email)
VALUES
('Galeriestraße', '10', '10115', 'Berlin', 'Deutschland', '030123456', 'kontakt@galerie-berlin.de'),
('Kunstallee', '22b', '50667', 'Köln', 'Deutschland', '0221123456', 'info@kunst-koeln.de');
-- Ausstellung-Daten
INSERT INTO event (location_id, start_date, end_date, name, description, max_tickets, ticket_price)
VALUES
(1, '2025-07-01', '2025-08-31', 'Moderne Meisterwerke', 'Eine Sammlung moderner Kunstwerke aus Europa.', 200, 19.99),
(2, '2025-09-10', '2025-10-20', 'Kunst der Antike', 'Ausstellung antiker Skulpturen und Gemälde.', 150, 39.99);
-- Gutschein-Daten
INSERT INTO voucher (code, discount, event_id, valid_until)
VALUES
('SOMMER2025', 15, 1, '2025-08-31'),
('HERBST25', 25, 2, '2025-10-15');
-- Ticket-Daten
INSERT INTO ticket (user_id, event_id, purchase_date, valid_until)
VALUES
(1, 1, '2025-06-01', '2025-07-15'),
(2, 2, '2025-06-05', '2025-09-15');
-- News-Daten
INSERT INTO news (name, description, date)
VALUES
('Branchen-News: bibarts schließt strategische Partnerschaft mit regionalen Veranstaltern', 'Die aufstrebende Ticketplattform bibarts hat heute eine Partnerschaft mit mehreren regionalen Veranstaltungsagenturen in Süddeutschland bekannt gegeben. Ziel der Zusammenarbeit ist die gemeinsame Digitalisierung lokaler Events und die Vereinfachung des Ticketverkaufsprozesses für kleinere Veranstalter.
Viele unserer Kunden sind Künstlerkollektive, Kulturvereine oder Betreiber kleiner Bühnen für sie war der Einstieg in den digitalen Ticketverkauf bisher kompliziert oder zu teuer, erklärt der Vertriebsleiter von bibarts.
Durch die Partnerschaft erhalten Veranstalter Zugang zu einem vereinfachten Onboarding-System, einer automatisierten Veranstaltungsverwaltung und einem integrierten Zahlungssystem. bibarts stellt zudem eigene Event-Widgets bereit, die direkt in bestehende Websites eingebettet werden können.
Die ersten Live-Tests starten im Juli auf Veranstaltungen in Augsburg, Regensburg und Rosenheim. Bei Erfolg soll das Modell bundesweit ausgerollt werden. Marktanalysten sehen in bibarts einen ernstzunehmenden Konkurrenten für etablierte Anbieter wie Eventim oder Reservix vor allem im Bereich Nischen- und Indie-Veranstaltungen.', '2025-06-01'),
('bibarts bringts: Neue Ticketplattform sorgt für Chaos auf der Poetry-Slam-Bühne aber im besten Sinne', '„Niemand hat damit gerechnet, dass Poetry & Pizza Vol. 7 restlos ausverkauft sein würde außer vielleicht bibarts.“ So beschreibt der Veranstalter des beliebten Slam-Formats in Hamburg-Altona die Überraschung des Abends.
Dank der neuen Ticketplattform bibarts, die laut Insidern selbst mit einem Toaster kompatibel sei, wurden innerhalb von 48 Stunden über 300 Tickets verkauft komplett online, ohne Papierkram, ohne Warteschlangen.
Doch die größte Überraschung: Die Slammer wurden beim Einlass mit QR-Codes auf Bananen begrüßt ein kreatives Gimmick von bibarts Entwicklerteam, das einen Testlauf für alternative Ticketträger durchführt. Laut Veranstalter kamen fast 30 Gäste mit beschrifteten Bananen zum Einlass der Scanner erkannte alle korrekt. 🍌
Wenn Technik und Kultur auf diese Weise verschmelzen, haben wir etwas richtig gemacht, scherzte ein Sprecher von bibarts nach der Show. Auch wenn die Banane wohl kein langfristiges Ticketmedium wird, sei der Abend ein voller Erfolg gewesen sowohl auf als auch vor der Bühne.', '2025-05-20'),
('bibarts launcht Wartelistenfunktion und füllt plötzlich leergebliebene Reihen', 'Mit einem neuen Feature sorgt bibarts erneut für Schlagzeilen: Die Plattform hat kürzlich eine intelligente Wartelistenfunktion eingeführt, die automatisch frei gewordene Plätze an Interessierte nachbesetzt ein Gamechanger für spontane Events und kurzfristige Absagen.
Beim ersten Einsatz bei einem Impro-Theater in Köln meldeten sich über 40 Personen für die Warteliste. Als drei Gruppen krankheitsbedingt absagen mussten, sprang das System ein und verschickte automatisch neue Tickets an Wartende. Innerhalb von 15 Minuten waren die Plätze wieder gefüllt.
Wir konnten dadurch die Show vor vollem Haus spielen ohne Einnahmeverluste, sagt die Theaterleitung. Das Feature basiert auf einem Prioritätssystem, das Fairness und Schnelligkeit kombiniert und sogar per SMS benachrichtigt.
bibarts plant, die Funktion in Zukunft noch zu erweitern etwa mit Echtzeit-Übersicht für Veranstalter oder integrierter Last-Minute-Werbung.', '2025-06-20');

View File

@ -1,30 +0,0 @@
-- phpMyAdmin SQL Dump
-- version 4.5.1
-- http://www.phpmyadmin.net
--
-- Host: 127.0.0.1
-- Erstellungszeit: 24. Nov 2017 um 17:01
-- Server-Version: 10.1.16-MariaDB
-- PHP-Version: 7.0.9
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
--
-- Datenbank: `blog`
--
-- --------------------------------------------------------
CREATE TABLE `contact` (
`id` varchar(36) NOT NULL,
`topicCode` tinyint(2) NULL,
`name` varchar(200) NOT NULL,
`email` varchar(300) NOT NULL,
`phone` varchar(16) NULL,
`content` varchar(500) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `contact`
ADD PRIMARY KEY (`id`)

BIN
images/Zahlungsmittel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
images/bibArts.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,7 +1,8 @@
<?php
session_start();;;
session_start();
include 'Views/header.phtml';
?>
<?php
spl_autoload_register(function ($className) {
if (substr($className, 0, 5) !== 'Blog\\') {
// not our business
@ -40,6 +41,8 @@ if (method_exists($controllerClassName, $doMethodName)) {
} else {
new \Blog\Library\ErrorMsg('Page not found: '.$controllerClassName.'::'.$doMethodName);
}
?>
<?php
include 'Views/footer.phtml';
?>