Feat: Add contacts
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20231016090702 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE contact (id INT AUTO_INCREMENT NOT NULL, photo_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, destination VARCHAR(255) DEFAULT NULL, UNIQUE INDEX UNIQ_4C62E6387E9E4C8C (photo_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E6387E9E4C8C FOREIGN KEY (photo_id) REFERENCES upload (id)');
|
||||
$this->addSql('ALTER TABLE user ADD contact_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE user ADD CONSTRAINT FK_8D93D649E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id)');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649E7A1254A ON user (contact_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE user DROP FOREIGN KEY FK_8D93D649E7A1254A');
|
||||
$this->addSql('ALTER TABLE contact DROP FOREIGN KEY FK_4C62E6387E9E4C8C');
|
||||
$this->addSql('DROP TABLE contact');
|
||||
$this->addSql('DROP INDEX UNIQ_8D93D649E7A1254A ON user');
|
||||
$this->addSql('ALTER TABLE user DROP contact_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Contact;
|
||||
|
||||
use App\Entity\Contact;
|
||||
use App\Entity\Upload;
|
||||
use App\Entity\User;
|
||||
use App\Form\ContactType;
|
||||
use App\Model\AjaxModalResponseDto;
|
||||
use App\Service\Upload\UploadHandler;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UploadHandler $uploadHandler,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/contact/create', name: 'app_admin_system_contact_create')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$response = new AjaxModalResponseDto();
|
||||
$contact = new Contact();
|
||||
$formAction = $this->generateUrl('app_admin_system_contact_create');
|
||||
|
||||
// Handle upload independently from form submission to avoid issues with failing validation
|
||||
$uploadSession = $this->uploadHandler->getUploadSession();
|
||||
if (true === $request->isMethod('POST') && 0 < $uploadSession->getCount()) {
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
|
||||
$photo = Upload::fromUploadDto($uploadSession->getUploads()->first(), $user, Upload::TYPE_PHOTO);
|
||||
$contact->setPhoto($photo);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->uploadHandler->moveUploadSessionFilesFromOrphanage(Upload::TYPE_PHOTO, $uploadSession);
|
||||
$this->uploadHandler->destroyUploadSession();
|
||||
}
|
||||
|
||||
$form = $this->createForm(
|
||||
ContactType::class,
|
||||
$contact,
|
||||
[
|
||||
'action' => $formAction,
|
||||
'ajax_submit' => true,
|
||||
'upload_session' => $uploadSession,
|
||||
]
|
||||
);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->persist($contact);
|
||||
$this->entityManager->flush();
|
||||
$this->addFlash('success', 'Der Ansprechpartner wurde hinzugefügt');
|
||||
$this->logger->info('Create contact', [
|
||||
'contact' => $contact->getName(),
|
||||
]);
|
||||
|
||||
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_contact_index'));
|
||||
} else {
|
||||
$response->setContent($this->renderView('admin/system/contact/create.html.twig', [
|
||||
'form' => $form,
|
||||
]));
|
||||
}
|
||||
|
||||
return $this->json($response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Contact;
|
||||
|
||||
use App\Entity\Contact;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/contact/delete/{id}', name: 'app_admin_system_contact_delete')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Contact $contact): Response
|
||||
{
|
||||
$this->entityManager->remove($contact);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Ansprechpartner wurde gelöscht');
|
||||
$this->logger->info('Delete contact', [
|
||||
'contact' => $contact->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_contact_index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Contact;
|
||||
|
||||
use App\Entity\Contact;
|
||||
use App\Entity\Upload;
|
||||
use App\Entity\User;
|
||||
use App\Form\ContactType;
|
||||
use App\Model\AjaxModalResponseDto;
|
||||
use App\Service\Upload\UploadHandler;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class EditController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UploadHandler $uploadHandler,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/contact/edit/{id}', name: 'app_admin_system_contact_edit')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Contact $contact, Request $request): JsonResponse
|
||||
{
|
||||
$response = new AjaxModalResponseDto();
|
||||
$formAction = $this->generateUrl('app_admin_system_contact_edit', ['id' => $contact->getId()]);
|
||||
// Handle upload independently from form submission to avoid issues with failing validation
|
||||
$uploadSession = $this->uploadHandler->getUploadSession();
|
||||
if (true === $request->isMethod('POST') && 0 < $uploadSession->getCount()) {
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$photo = Upload::fromUploadDto($uploadSession->getUploads()->first(), $user, Upload::TYPE_PHOTO);
|
||||
if (null !== $existingPhoto = $contact->getPhoto()) {
|
||||
$this->entityManager->remove($existingPhoto);
|
||||
}
|
||||
$contact->setPhoto($photo);
|
||||
$this->entityManager->flush();
|
||||
$this->uploadHandler->moveUploadSessionFilesFromOrphanage(Upload::TYPE_PHOTO, $uploadSession);
|
||||
$this->uploadHandler->destroyUploadSession();
|
||||
}
|
||||
|
||||
$form = $this->createForm(
|
||||
ContactType::class,
|
||||
$contact,
|
||||
[
|
||||
'action' => $formAction,
|
||||
'ajax_submit' => true,
|
||||
'upload_session' => $uploadSession,
|
||||
]
|
||||
);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->flush();
|
||||
$this->addFlash('success', 'Der Ansprechpartner wurde aktualisiert');
|
||||
$this->logger->info('Edit contact', [
|
||||
'contact' => $contact->getName(),
|
||||
]);
|
||||
|
||||
$response->setCloseAndRedirect($this->generateUrl('app_admin_system_contact_index'));
|
||||
} else {
|
||||
$response->setContent($this->renderView('admin/system/contact/edit.html.twig', [
|
||||
'form' => $form,
|
||||
]));
|
||||
}
|
||||
|
||||
return $this->json($response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Contact;
|
||||
|
||||
use App\Repository\ContactRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly ContactRepository $contactRepository)
|
||||
{}
|
||||
|
||||
#[Route('/admin/system/contact', name: 'app_admin_system_contact_index')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(): Response
|
||||
{
|
||||
$contacts = $this
|
||||
->contactRepository
|
||||
->findBy([], ['name' => 'ASC'])
|
||||
;
|
||||
|
||||
return $this->render('admin/system/contact/index.html.twig', [
|
||||
'contacts' => $contacts,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,32 @@
|
||||
|
||||
namespace App\Controller\Teamer;
|
||||
|
||||
use App\Repository\ContactRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class ContactController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly ContactRepository $contactRepository)
|
||||
{}
|
||||
|
||||
#[Route('/teamer/contact', name: 'app_teamer_contact')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('teamer/contact/index.html.twig');
|
||||
$generalContacts = $this
|
||||
->contactRepository
|
||||
->getGeneralContacts()
|
||||
;
|
||||
|
||||
$destinationContacts = $this
|
||||
->contactRepository
|
||||
->getDestinationContacts()
|
||||
;
|
||||
|
||||
return $this->render('teamer/contact/index.html.twig', [
|
||||
'generalContacts' => $generalContacts,
|
||||
'destinationContacts' => $destinationContacts,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\ContactRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity(repositoryClass: ContactRepository::class)]
|
||||
class Contact
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Assert\NotBlank(message: 'Bitte gib den Namen an')]
|
||||
private ?string $name = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Assert\NotBlank(message: 'Bitte gib die E-Mail-Adresse an')]
|
||||
#[Assert\Email(message: 'Bitte gib eine gültige E-Mail-Adresse an', mode: 'strict')]
|
||||
private ?string $email = null;
|
||||
|
||||
#[ORM\OneToOne(cascade: ['persist', 'remove'], fetch: 'EAGER')]
|
||||
#[Assert\NotNull(message: 'Bitte lade ein Foto hoch')]
|
||||
private ?Upload $photo = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $destination = null;
|
||||
|
||||
#[ORM\OneToOne(mappedBy: 'contact', cascade: ['persist', 'remove'], fetch: 'EXTRA_LAZY')]
|
||||
private ?User $user = null;
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPhoto(): ?Upload
|
||||
{
|
||||
return $this->photo;
|
||||
}
|
||||
|
||||
public function setPhoto(?Upload $photo): static
|
||||
{
|
||||
$this->photo = $photo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDestination(): ?string
|
||||
{
|
||||
return $this->destination;
|
||||
}
|
||||
|
||||
public function setDestination(?string $destination): static
|
||||
{
|
||||
$this->destination = $destination;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function setUser(?User $user): static
|
||||
{
|
||||
// unset the owning side of the relation if necessary
|
||||
if ($user === null && $this->user !== null) {
|
||||
$this->user->setContact(null);
|
||||
}
|
||||
|
||||
// set the owning side of the relation if necessary
|
||||
if ($user !== null && $user->getContact() !== $this) {
|
||||
$user->setContact($this);
|
||||
}
|
||||
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class Teamer implements TimestampableEntityInterface
|
||||
#[ORM\OneToMany(mappedBy: 'teamer', targetEntity: Disposition::class, cascade: ['remove'])]
|
||||
private Collection $dispositions;
|
||||
|
||||
#[ORM\OneToOne(mappedBy: 'teamer')]
|
||||
#[ORM\OneToOne(mappedBy: 'teamer', fetch: 'EXTRA_LAZY')]
|
||||
private ?User $user = null;
|
||||
|
||||
#[ORM\Column]
|
||||
|
||||
@@ -45,6 +45,9 @@ class User implements UserInterface, TimestampableEntityInterface
|
||||
#[ORM\OneToOne(inversedBy: 'user', cascade: ['persist', 'remove'])]
|
||||
private ?Teamer $teamer = null;
|
||||
|
||||
#[ORM\OneToOne(inversedBy: 'user', cascade: ['persist', 'remove'])]
|
||||
private ?Contact $contact = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->uuid = Uuid::v4();
|
||||
@@ -200,4 +203,16 @@ class User implements UserInterface, TimestampableEntityInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContact(): ?Contact
|
||||
{
|
||||
return $this->contact;
|
||||
}
|
||||
|
||||
public function setContact(?Contact $contact): static
|
||||
{
|
||||
$this->contact = $contact;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Contact;
|
||||
use App\Model\UploadSessionDto;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ContactType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('name', TextType::class, [
|
||||
'label' => 'Name',
|
||||
])
|
||||
->add('email', EmailType::class, [
|
||||
'label' => 'E-Mail',
|
||||
])
|
||||
->add('destination', TextType::class, [
|
||||
'label' => 'Destination',
|
||||
'required' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver
|
||||
->setDefaults([
|
||||
'data_class' => Contact::class,
|
||||
])
|
||||
->setRequired(['upload_session'])
|
||||
->setAllowedTypes('upload_session', UploadSessionDto::class)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,10 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
'route' => 'app_admin_system_document_index',
|
||||
'title' => 'Dokumente',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_contact_index',
|
||||
'title' => 'Ansprechpartner',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Contact;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Contact>
|
||||
*
|
||||
* @method Contact|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Contact|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Contact[] findAll()
|
||||
* @method Contact[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ContactRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Contact::class);
|
||||
}
|
||||
|
||||
public function getGeneralContacts(): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('contact');
|
||||
|
||||
return $qb
|
||||
->leftJoin('contact.photo', 'photo')
|
||||
->where($qb->expr()->isNull('contact.destination'))
|
||||
->orderBy('contact.name', 'ASC')
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
|
||||
public function getDestinationContacts(): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('contact');
|
||||
|
||||
return $qb
|
||||
->leftJoin('contact.photo', 'photo')
|
||||
->where($qb->expr()->isNotNull('contact.destination'))
|
||||
->orderBy('contact.name', 'ASC')
|
||||
->addOrderBy('contact.destination', 'ASC')
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-4">
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.email) }}
|
||||
{{ form_row(form.destination) }}
|
||||
<div>
|
||||
<h4 class="font-bold pb-2">
|
||||
Foto
|
||||
</h4>
|
||||
{% include '_partials/_upload_collection_form.html.twig' with {
|
||||
'endpoint_upload': path('_uploader_upload_photo'),
|
||||
'max_filesize': 5,
|
||||
'max_files': 1,
|
||||
'accepted_files': 'image/jpg,image/jpeg',
|
||||
} %}
|
||||
{{ form_errors(form) }}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
@@ -0,0 +1 @@
|
||||
{% include 'admin/system/contact/_form.html.twig' %}
|
||||
@@ -0,0 +1 @@
|
||||
{% include 'admin/system/contact/_form.html.twig' %}
|
||||
@@ -0,0 +1,81 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Ansprechpartner{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Ansprechpartner
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Name
|
||||
</th>
|
||||
<th>
|
||||
E-Mail
|
||||
</th>
|
||||
<th>
|
||||
Destination
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for contact in contacts %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ contact.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ contact.email }}
|
||||
</td>
|
||||
<td>
|
||||
{{ contact.destination|default('-') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du den Ansprechpartner wirklich löschen?',
|
||||
'target-url': path('app_admin_system_contact_delete', { 'id': contact.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
<button type="button"
|
||||
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'ajax', null, {
|
||||
'title': 'Ansprechpartner bearbeiten',
|
||||
'url': path('app_admin_system_contact_edit', { 'id': contact.id })
|
||||
}) }}>
|
||||
{{ icon('edit') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
Keine Daten...
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button"
|
||||
class="btn"
|
||||
{{ stimulus_controller('modal-button', [], [], {'ajax-modal': '#ajax-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'ajax', null, {
|
||||
'title': 'Ansprechpartner hinzufügen',
|
||||
'url': path('app_admin_system_contact_create')
|
||||
}) }}>
|
||||
Neu
|
||||
</button>
|
||||
{% endblock %}
|
||||
@@ -85,6 +85,7 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
<button type="button"
|
||||
|
||||
@@ -2,8 +2,55 @@
|
||||
|
||||
{% block title %}Kontakt{% endblock %}
|
||||
|
||||
{% macro contacts(contacts, email) %}
|
||||
<div class="pb-8">
|
||||
<div class="flex justify-center">
|
||||
<div class="flex flex-wrap items-center">
|
||||
{% for contact in contacts %}
|
||||
<div class="flex flex-col items-center space-y-2 px-8 py-4">
|
||||
{% if contact.photo %}
|
||||
<img src="{{ asset(contact.photo.filename | imagine_filter('profile')) }}"
|
||||
class="w-32 h-auto border-2 border-primary rounded-full"
|
||||
alt="{{ contact.name }}">
|
||||
{% endif %}
|
||||
<div class="font-bold">
|
||||
{{ contact.name }}
|
||||
</div>
|
||||
{% if contact.destination %}
|
||||
<div>
|
||||
{{ contact.destination }}
|
||||
</div>
|
||||
<div>
|
||||
<a href="mailto:{{ contact.email }}" class="underline">{{ contact.email }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% if email %}
|
||||
<div class="text-center">
|
||||
<a href="mailto:{{ email }}" class="text-lg fobt-bold underline">{{ email }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Kontakt
|
||||
</h1>
|
||||
<p class="pb-4">
|
||||
Hast du allgemeine Fragen zum Teamer-sein bei E&P Reisen, zur Benutzung von MyE&P Team, zur Abrechnung
|
||||
oder Sonstigem? Hast du schon geschaut, ob deine Frage in den FAQs beantwortet wird?
|
||||
</p>
|
||||
<p>
|
||||
Dann melde dich gerne beim Team Personalplanung!
|
||||
</p>
|
||||
{{ _self.contacts(generalContacts, '[email protected]') }}
|
||||
<p>
|
||||
Hast du Fragen zu deinem nächsten Einsatz in einer konkreten Destination? Dann melde dich gerne bei der*dem
|
||||
zuständigen Reisemanager*in!
|
||||
</p>
|
||||
{{ _self.contacts(destinationContacts) }}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user