Compare commits

...

5 Commits

18 changed files with 1733 additions and 159 deletions

View File

@ -7,8 +7,8 @@ xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
database:
type: mariadb
version: "10.11"
type: postgres
version: "17"
use_dns_when_possible: true
composer_version: "2"
web_environment: []

10
.env
View File

@ -24,3 +24,13 @@ MAILER_DSN=smtp://${MAILER_USER:-null}:${MAILER_PASSWORD:-null}@${MAILER_HOST:-l
CONTACT_MAIL=${CONTACT_MAIL:-contact@localhost}
SENDER_MAIL=${SENDER_MAIL:-noreply@localhost}
###< symfony/mailer ###
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###

View File

@ -7,7 +7,12 @@
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.13",
"doctrine/doctrine-migrations-bundle": "^3.4",
"doctrine/orm": "^3.3",
"php-flasher/flasher-noty-symfony": "^2.1",
"stripe/stripe-php": "^16.4",
"symfony/asset": "7.2.*",
"symfony/asset-mapper": "7.2.*",
"symfony/console": "7.2.*",

1527
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -9,4 +9,6 @@ return [
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Flasher\Symfony\FlasherSymfonyBundle::class => ['all' => true],
Flasher\Noty\Symfony\FlasherNotySymfonyBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
];

View File

@ -0,0 +1,54 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '16'
profiling_collect_backtrace: '%kernel.debug%'
use_savepoints: true
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
report_fields_where_declared: true
validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
identity_generation_preferences:
Doctrine\DBAL\Platforms\PostgreSQLPlatform: identity
auto_mapping: true
mappings:
App:
type: attribute
is_bundle: false
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
controller_resolver:
auto_mapping: false
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system

View File

@ -0,0 +1,6 @@
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations'
enable_profiler: false

0
migrations/.gitignore vendored Normal file
View File

View File

@ -0,0 +1,24 @@
<?php
namespace App\Controller;
use App\DataObjects\TicketData;
use App\Form\TicketForm;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class TicketController extends AbstractController
{
#[Route('/ticket', name: 'app_ticket')]
public function index(Request $request): Response
{
$data = new TicketData();
$form = $this->createForm(TicketForm::class, $data)->handleRequest($request);
return $this->render('ticket/index.html.twig', [
'form' => $form->createView(),
]);
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\DataObjects;
class TicketData
{
public function __construct(
public string $notes = '',
public int $ticket = 0,
public int $afterShowTicket = 0,
) {
}
}

0
src/Entity/.gitignore vendored Normal file
View File

95
src/Entity/Ticket.php Normal file
View File

@ -0,0 +1,95 @@
<?php
namespace App\Entity;
use App\Repository\TicketRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: TicketRepository::class)]
class Ticket
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $email = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $phone = null;
#[ORM\Column(length: 255)]
private ?string $firstname = null;
#[ORM\Column(length: 255)]
private ?string $lastname = null;
#[ORM\Column]
private int $quantity = 0;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): static
{
$this->email = $email;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(?string $phone): static
{
$this->phone = $phone;
return $this;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(string $firstname): static
{
$this->firstname = $firstname;
return $this;
}
public function getLastname(): ?string
{
return $this->lastname;
}
public function setLastname(string $lastname): static
{
$this->lastname = $lastname;
return $this;
}
public function getQuantity(): int
{
return $this->quantity;
}
public function setQuantity(int $quantity): static
{
$this->quantity = $quantity;
return $this;
}
}

21
src/Form/TicketForm.php Normal file
View File

@ -0,0 +1,21 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
class TicketForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('ticket', NumberType::class)
->add('afterShowTicket', NumberType::class)
->add('notes', TextareaType::class);
}
}

0
src/Repository/.gitignore vendored Normal file
View File

View File

@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\Ticket;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Ticket>
*/
class TicketRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Ticket::class);
}
// /**
// * @return Ticket[] Returns an array of Ticket objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('t')
// ->andWhere('t.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('t.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Ticket
// {
// return $this->createQueryBuilder('t')
// ->andWhere('t.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View File

@ -1,4 +1,31 @@
{
"doctrine/doctrine-bundle": {
"version": "2.13",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.13",
"ref": "8d96c0b51591ffc26794d865ba3ee7d193438a83"
},
"files": [
"config/packages/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"php-flasher/flasher-noty-symfony": {
"version": "v2.1.2"
},

View File

@ -26,7 +26,7 @@
</div>
<div class="text-center space-y-6">
<a href="" class="inline-block bg-gradient-to-r from-red-500 to-orange-500 hover:from-red-600 hover:to-orange-600 text-white px-8 sm:px-10 md:px-12 py-4 sm:py-5 rounded-full text-base sm:text-lg font-semibold shadow-xl hover:shadow-2xl transition-all duration-300">
<a href="{{ path('app_ticket') }}" class="inline-block bg-gradient-to-r from-red-500 to-orange-500 hover:from-red-600 hover:to-orange-600 text-white px-8 sm:px-10 md:px-12 py-4 sm:py-5 rounded-full text-base sm:text-lg font-semibold shadow-xl hover:shadow-2xl transition-all duration-300">
Tickets kaufen
</a>
</div>

View File

@ -0,0 +1,59 @@
{% extends 'base.html.twig' %}
{% block title %}Tickets kaufen{% endblock %}
{% block body %}
<div class="min-h-screen bg-gradient-to-br from-yellow-50 via-white to-orange-50 relative overflow-hidden">
<header class="w-full bg-white/90 backdrop-blur-md shadow-lg fixed top-0 z-50 border-b border-gray-100">
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-3 sm:py-4 flex justify-between items-center">
<a href="{{ path('app_home') }}">
<img src="{{ asset('images/logo.png') }}" alt="Logo" class="w-32 sm:w-36 md:w-40 h-auto hover:opacity-90 transition-opacity" />
</a>
<a href="{{ path('app_home') }}" class="bg-gradient-to-r from-red-500 to-orange-500 hover:from-red-600 hover:to-orange-600 text-white px-4 sm:px-6 md:px-8 py-2 sm:py-2.5 rounded-full text-xs sm:text-sm font-medium shadow-md hover:shadow-lg transition-all duration-300">
Zurück zur Startseite
</a>
</div>
</header>
<main class="container mx-auto px-4 sm:px-6 lg:px-8 pt-24 sm:pt-28 md:pt-32 pb-16 sm:pb-20 flex flex-col items-center justify-center relative z-10">
<div class="w-full max-w-2xl">
<h1 class="text-3xl sm:text-4xl md:text-5xl font-bold text-gray-800 text-center mb-6 sm:mb-8 tracking-tight leading-tight">
<span class="bg-clip-text text-transparent bg-gradient-to-r from-red-500 to-orange-500">Tickets kaufen</span>
</h1>
<div class="bg-white/80 backdrop-blur-md shadow-xl rounded-2xl sm:rounded-3xl p-6 sm:p-8 md:p-10 mb-12 sm:mb-16 transform transition-all duration-300 border border-gray-100">
{{ form_start(form, { 'attr': { 'class': 'space-y-6' } }) }}
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div>
<label for="firstname" class="block text-sm font-medium text-gray-700 mb-1">Vorname *</label>
<input type="text" name="{{ field_name(form.ticket) }}" id="firstname" required
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500 transition-colors">
</div>
<div>
<label for="lastname" class="block text-sm font-medium text-gray-700 mb-1">Nachname *</label>
<input type="text" name="{{ field_name(form.afterShowTicket) }}" id="lastname" required
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500 transition-colors">
</div>
</div>
<div>
<label for="notes" class="block text-sm font-medium text-gray-700 mb-1">Anmerkungen</label>
<textarea name="{{ field_name(form.notes) }}" id="notes" rows="4"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500 transition-colors"
placeholder="Optionale Anmerkungen zu Ihrer Bestellung"></textarea>
</div>
<div class="text-center pt-4">
<button type="submit"
class="w-full sm:w-auto inline-block bg-gradient-to-r from-red-500 to-orange-500 hover:from-red-600 hover:to-orange-600 text-white px-8 sm:px-10 py-3 rounded-full text-base font-semibold shadow-xl hover:shadow-2xl transition-all duration-300">
Ticket bestellen
</button>
</div>
{{ form_end(form) }}
</div>
</div>
</main>
</div>
{% endblock %}