WIP: Implement application process
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?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 Version20231009130251 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('ALTER TABLE application ADD uuid VARCHAR(36) NOT NULL');
|
||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_A45BDDC1D17F50A6 ON application (uuid)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP INDEX UNIQ_A45BDDC1D17F50A6 ON application');
|
||||
$this->addSql('ALTER TABLE application DROP uuid');
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer;
|
||||
namespace App\Controller\Teamer\Application;
|
||||
|
||||
use App\Entity\Application;
|
||||
use App\Entity\Assignment;
|
||||
@@ -14,7 +14,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class ApplicationController extends AbstractController
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
@@ -22,8 +22,9 @@ class ApplicationController extends AbstractController
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/teamer/application/{uuid}', name: 'app_teamer_application')]
|
||||
#[Route('/teamer/apply/{uuid}', name: 'app_teamer_application_create')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
#[IsGranted('APPLY', subject: 'assignment')]
|
||||
public function index(Assignment $assignment, Request $request): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
@@ -47,7 +48,7 @@ class ApplicationController extends AbstractController
|
||||
return $this->redirectToRoute('app_teamer_index');
|
||||
}
|
||||
|
||||
return $this->render('teamer/application.html.twig', [
|
||||
return $this->render('teamer/application/create.html.twig', [
|
||||
'assignment' => $assignment,
|
||||
'teamer' => $teamer,
|
||||
'form' => $form,
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Application;
|
||||
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Entity\Application;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
use ReturnUrlTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/teamer/application/delete/{uuid}', name: 'app_teamer_application_delete')]
|
||||
#[IsGranted('DELETE', subject: 'application')]
|
||||
public function index(Application $application, Request $request): Response
|
||||
{
|
||||
$this->entityManager->remove($application);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->logger->info('Delete application', [
|
||||
'application' => $application->getUuid(),
|
||||
]);
|
||||
|
||||
$returnUrl = $this->getReturnUrl($request, 'app_teamer_index');
|
||||
|
||||
return $this->redirect($returnUrl);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Controller\Teamer;
|
||||
|
||||
use App\Entity\Assignment;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ApplicationRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
@@ -10,12 +12,30 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class AssignmentController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly ApplicationRepository $applicationRepository)
|
||||
{}
|
||||
|
||||
#[Route('/teamer/assignment/{uuid}', name: 'app_teamer_assignment')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
public function index(Assignment $assignment): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
$application = $this
|
||||
->applicationRepository
|
||||
->findOneBy([
|
||||
'assignment' => $assignment,
|
||||
'teamer' => $teamer,
|
||||
])
|
||||
;
|
||||
|
||||
return $this->render('teamer/assignment.html.twig', [
|
||||
'teamer' => $teamer,
|
||||
'assignment' => $assignment,
|
||||
'application' => $application,
|
||||
'isBookmarked' => $teamer->getBookmarks()->contains($assignment),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer\Bookmark;
|
||||
|
||||
use App\Controller\Traits\ReturnUrlTrait;
|
||||
use App\Entity\Assignment;
|
||||
use App\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class ToggleController extends AbstractController
|
||||
{
|
||||
use ReturnUrlTrait;
|
||||
|
||||
public function __construct(private readonly EntityManagerInterface $entityManager)
|
||||
{}
|
||||
|
||||
#[Route('/teamer/bookmark/toggle/{uuid}', name: 'app_teamer_bookmark_toggle')]
|
||||
#[IsGranted('ROLE_TEAMER')]
|
||||
public function index(Assignment $assignment, Request $request): Response
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
|
||||
if ($teamer->getBookmarks()->contains($assignment)) {
|
||||
$teamer->removeBookmark($assignment);
|
||||
$this->addFlash('success', 'Der Einsatz wurde von der Merkliste entfernt');
|
||||
} else {
|
||||
$teamer->addBookmark($assignment);
|
||||
$this->addFlash('success', 'Der Einsatz wurde auf die Merkliste gesetzt');
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$returnUrl = $this->getReturnUrl($request, 'app_teamer_index');
|
||||
|
||||
return $this->redirect($returnUrl);
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,6 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
private ?string $remarks = null;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: Fee::class)]
|
||||
#[Assert\Count(min: 1, minMessage: 'Bitte triff mindestens eine Auswahl')]
|
||||
private Collection $fees;
|
||||
|
||||
#[ORM\OneToMany(mappedBy: 'assignment', targetEntity: Application::class)]
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Form;
|
||||
use App\Entity\Application;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
@@ -15,36 +16,45 @@ class TeamerApplicationType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
|
||||
/** @var Application $application */
|
||||
$application = $event->getData();
|
||||
|
||||
if (null === $application) {
|
||||
return;
|
||||
}
|
||||
|
||||
$assignment = $application->getAssignment();
|
||||
|
||||
if (null === $assignment->getPickup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$teamer = $application->getTeamer();
|
||||
|
||||
if (in_array($assignment->getPickup(), $teamer->getPickups())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->getForm()->add('confirmPickup', CheckboxType::class, [
|
||||
'label' => 'Ich bestätige den abweichenden Buszustieg',
|
||||
'mapped' => false,
|
||||
'constraints' => [
|
||||
new IsTrue([
|
||||
'message' => 'Deine Bestätigung ist erforderlich',
|
||||
]),
|
||||
$builder
|
||||
->add('requests', TextareaType::class, [
|
||||
'label' => 'Wünsche',
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'rows' => 3,
|
||||
],
|
||||
]);
|
||||
});
|
||||
])
|
||||
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
|
||||
/** @var Application $application */
|
||||
$application = $event->getData();
|
||||
|
||||
if (null === $application) {
|
||||
return;
|
||||
}
|
||||
|
||||
$assignment = $application->getAssignment();
|
||||
|
||||
if (null === $assignment->getPickup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$teamer = $application->getTeamer();
|
||||
|
||||
if (in_array($assignment->getPickup(), $teamer->getPickups())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->getForm()->add('confirmPickup', CheckboxType::class, [
|
||||
'label' => 'Ich bestätige den abweichenden Buszustieg',
|
||||
'mapped' => false,
|
||||
'constraints' => [
|
||||
new IsTrue([
|
||||
'message' => 'Deine Bestätigung ist erforderlich',
|
||||
]),
|
||||
],
|
||||
]);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Assignment;
|
||||
use App\Entity\Teamer;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
@@ -22,11 +23,24 @@ class AssignmentRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, Assignment::class);
|
||||
}
|
||||
|
||||
public function getListQuery(): Query
|
||||
public function getListQuery(Teamer $teamer = null): Query
|
||||
{
|
||||
return $this
|
||||
->createQueryBuilder('assignment')
|
||||
->getQuery()
|
||||
$qb = $this->createQueryBuilder('assignment');
|
||||
|
||||
$qb
|
||||
->select('assignment', 'destination', 'job_profile', 'application')
|
||||
->innerJoin('assignment.destination', 'destination')
|
||||
->innerJoin('assignment.jobProfile', 'job_profile')
|
||||
->leftJoin('assignment.applications', 'application')
|
||||
;
|
||||
|
||||
if (null !== $teamer) {
|
||||
$qb
|
||||
->where($qb->expr()->eq('application.teamer', ':teamer'))
|
||||
->setParameter('teamer', $teamer)
|
||||
;
|
||||
}
|
||||
|
||||
return $qb->getQuery();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Entity\Application;
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
|
||||
class ApplicationVoter extends Voter
|
||||
{
|
||||
public const VIEW = 'VIEW';
|
||||
public const DELETE = 'DELETE';
|
||||
|
||||
protected function supports(string $attribute, mixed $subject): bool
|
||||
{
|
||||
if (!$subject instanceof Application) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($attribute, [static::VIEW, static::DELETE]);
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $token->getUser();
|
||||
|
||||
/** @var Application $application */
|
||||
$application = $subject;
|
||||
|
||||
if ($user->hasRole('ROLE_ADMINISTRATIVE')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($user->hasRole('ROLE_TEAMER')) {
|
||||
return $user->getTeamer() === $application->getTeamer();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
use App\Entity\Assignment;
|
||||
use App\Entity\User;
|
||||
use App\Repository\ApplicationRepository;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
|
||||
class AssignmentVoter extends Voter
|
||||
{
|
||||
public const VIEW = 'VIEW';
|
||||
public const EDIT = 'EDIT';
|
||||
public const APPLY = 'APPLY';
|
||||
|
||||
public function __construct(private readonly ApplicationRepository $applicationRepository)
|
||||
{}
|
||||
|
||||
protected function supports(string $attribute, mixed $subject): bool
|
||||
{
|
||||
if (!$subject instanceof Assignment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($attribute, [static::VIEW, static::EDIT, static::APPLY]);
|
||||
}
|
||||
|
||||
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
|
||||
{
|
||||
// All authenticated users may view assignments
|
||||
if (static::VIEW === $attribute && null !== $token->getUser()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only users with administrative role may edit assignments
|
||||
if (static::EDIT === $attribute && in_array('ROLE_ADMINISTRATIVE', $token->getRoleNames())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only teamers without existing applications may apply to the assignment
|
||||
if (in_array('ROLE_TEAMER', $token->getRoleNames())) {
|
||||
/** @var User $user */
|
||||
$user = $token->getUser();
|
||||
$teamer = $user->getTeamer();
|
||||
/** @var Assignment $assignment */
|
||||
$assignment = $subject;
|
||||
$application = $this->applicationRepository->findOneBy(['teamer' => $teamer, 'assignment' => $assignment]);
|
||||
|
||||
return null === $application;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-3">
|
||||
<div class="font-bold text-xl">
|
||||
Jobprofil
|
||||
</div>
|
||||
<div class="font-bold text-xl">
|
||||
{{ assignment.jobProfile.name }}
|
||||
</div>
|
||||
<div>
|
||||
Destination
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.destination.product }}
|
||||
<br>
|
||||
{{ assignment.destination.hotel }}
|
||||
</div>
|
||||
<div>
|
||||
Einsatztermin
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.totalPeriod.start|date('d.m.Y') }} - {{ assignment.totalPeriod.end|date('d.m.Y') }}
|
||||
</div>
|
||||
{% if assignment.pickup and assignment.pickupDate %}
|
||||
<div>
|
||||
Busabfahrt
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.pickupDate|date('d.m.Y') }}
|
||||
</div>
|
||||
<div>
|
||||
Busbegleitung
|
||||
</div>
|
||||
<div>
|
||||
ab {{ assignment.pickup|bpn_pickup_label }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
Du bekommst
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.benefits|nl2list }}
|
||||
</div>
|
||||
<div>
|
||||
Honorar
|
||||
</div>
|
||||
{% if assignment.fees|length %}
|
||||
<div>
|
||||
{% for fee in assignment.fees %}
|
||||
{{ fee.name }} {{ fee.value|format_money }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,26 @@
|
||||
<ul class="list-disc pl-4 pb-4">
|
||||
{% if assignment.pickup and assignment.pickupDate %}
|
||||
<li>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>Busbegleitung ab {{ assignment.pickup|bpn_pickup_label }} am {{ assignment.pickupDate|date('d.m.Y') }}</span>
|
||||
{% if teamer.hasPickup(assignment.pickup) %}
|
||||
{{ icon('check', 'w-5 h-5 text-emerald-500') }}
|
||||
{% else %}
|
||||
{{ icon('close', 'w-5 h-5 text-red-500') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for training in assignment.jobProfile.requiredTrainings %}
|
||||
<li>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>{{ training.name }} absolviert</span>
|
||||
{% if teamer.trainingAttendance(training) %}
|
||||
{{ icon('check', 'w-5 h-5 text-emerald-500') }}
|
||||
{% else %}
|
||||
{{ icon('close', 'w-5 h-5 text-red-500') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@@ -1,4 +0,0 @@
|
||||
{% extends 'manager/layout.html.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
@@ -1,9 +0,0 @@
|
||||
{% extends 'layout.html.twig' %}
|
||||
|
||||
{% block main_menu %}
|
||||
{{ knp_menu_render(knp_menu_get('manager_main')) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block mobile_menu %}
|
||||
{{ knp_menu_render(knp_menu_get('manager_main')) }}
|
||||
{% endblock %}
|
||||
@@ -1,101 +0,0 @@
|
||||
{% extends 'teamer/layout.html.twig' %}
|
||||
|
||||
{% block title %}Bewerbung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Bewerbung
|
||||
</h1>
|
||||
<div class="grid grid-cols-2 gap-8 items-start">
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-3 bg-gray-100 rounded-md p-4">
|
||||
<div class="font-bold text-xl">
|
||||
Jobprofil
|
||||
</div>
|
||||
<div class="font-bold text-xl">
|
||||
{{ assignment.jobProfile.name }}
|
||||
</div>
|
||||
<div>
|
||||
Destination
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.destination.product }}
|
||||
<br>
|
||||
{{ assignment.destination.hotel }}
|
||||
</div>
|
||||
<div>
|
||||
Einsatztermin
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.totalPeriod.start|date('d.m.Y') }} - {{ assignment.totalPeriod.end|date('d.m.Y') }}
|
||||
</div>
|
||||
{% if assignment.pickup and assignment.pickupDate %}
|
||||
<div>
|
||||
Busabfahrt
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.pickupDate|date('d.m.Y') }}
|
||||
</div>
|
||||
<div>
|
||||
Busbegleitung
|
||||
</div>
|
||||
<div>
|
||||
ab {{ assignment.pickup|bpn_pickup_label }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
Du bekommst
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.benefits|nl2list }}
|
||||
</div>
|
||||
<div>
|
||||
Honorar
|
||||
</div>
|
||||
<div>
|
||||
{% for fee in assignment.fees %}
|
||||
{{ fee.name }} {{ fee.value|format_money }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Voraussetzungen für diesen Einsatz
|
||||
</h2>
|
||||
<ul class="list-disc pl-4 pb-4">
|
||||
{% if assignment.pickup and assignment.pickupDate %}
|
||||
<li>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>Busbegleitung ab {{ assignment.pickup|bpn_pickup_label }} am {{ assignment.pickupDate|date('d.m.Y') }}</span>
|
||||
{% if teamer.hasPickup(assignment.pickup) %}
|
||||
{{ icon('check', 'w-5 h-5 text-emerald-500') }}
|
||||
{% else %}
|
||||
{{ icon('close', 'w-5 h-5 text-red-500') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for training in assignment.jobProfile.requiredTrainings %}
|
||||
<li>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>{{ training.name }} absolviert</span>
|
||||
{% if teamer.trainingAttendance(training) %}
|
||||
{{ icon('check', 'w-5 h-5 text-emerald-500') }}
|
||||
{% else %}
|
||||
{{ icon('close', 'w-5 h-5 text-red-500') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{{ form_start(form) }}
|
||||
{% if form.confirmPickup is defined %}
|
||||
{{ form_row(form.confirmPickup) }}
|
||||
{% endif %}
|
||||
<button type="submit" class="btn">
|
||||
Bewerbung einreichen
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,32 @@
|
||||
{% extends 'teamer/layout.html.twig' %}
|
||||
|
||||
{% block title %}Bewerbung{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Bewerbung
|
||||
</h1>
|
||||
<div class="grid grid-cols-2 gap-8 items-start">
|
||||
<div class="bg-gray-100 rounded-md p-4">
|
||||
{% include '_partials/_assignment_info.html.twig' %}
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Voraussetzungen für diesen Einsatz
|
||||
</h2>
|
||||
{% include '_partials/_assignment_requirements_info.html.twig' %}
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{% if form.confirmPickup is defined %}
|
||||
{{ form_row(form.confirmPickup) }}
|
||||
{% endif %}
|
||||
{{ form_row(form.requests) }}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
Bewerbung abschicken!
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -7,78 +7,46 @@
|
||||
Einsatzübersicht
|
||||
</h1>
|
||||
<div class="grid grid-cols-2 gap-8 items-start">
|
||||
<div class="grid grid-cols-2 gap-x-4 gap-y-3 bg-gray-100 rounded-md p-4">
|
||||
<div class="font-bold text-xl">
|
||||
Jobprofil
|
||||
</div>
|
||||
<div class="font-bold text-xl">
|
||||
{{ assignment.jobProfile.name }}
|
||||
</div>
|
||||
<div>
|
||||
Destination
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.destination.product }}
|
||||
<br>
|
||||
{{ assignment.destination.hotel }}
|
||||
</div>
|
||||
<div>
|
||||
Einsatztermin
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.totalPeriod.start|date('d.m.Y') }} - {{ assignment.totalPeriod.end|date('d.m.Y') }}
|
||||
</div>
|
||||
{% if assignment.pickup and assignment.pickupDate %}
|
||||
<div>
|
||||
Busabfahrt
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.pickupDate|date('d.m.Y') }}
|
||||
</div>
|
||||
<div>
|
||||
Busbegleitung
|
||||
</div>
|
||||
<div>
|
||||
ab {{ assignment.pickup|bpn_pickup_label }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
Du bekommst
|
||||
</div>
|
||||
<div>
|
||||
{{ assignment.benefits|nl2list }}
|
||||
</div>
|
||||
<div>
|
||||
Honorar
|
||||
</div>
|
||||
<div>
|
||||
{% for fee in assignment.fees %}
|
||||
{{ fee.name }} {{ fee.value|format_money }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="bg-gray-100 rounded-md p-4">
|
||||
{% include '_partials/_assignment_info.html.twig' %}
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-xl font-bold pb-2">
|
||||
Voraussetzungen für diesen Einsatz
|
||||
</h2>
|
||||
<ul class="list-disc pl-4 pb-4">
|
||||
{% if assignment.pickup and assignment.pickupDate %}
|
||||
<li>
|
||||
Busbegleitung ab {{ assignment.pickup|bpn_pickup_label }} am {{ assignment.pickupDate|date('d.m.Y') }}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for training in assignment.jobProfile.requiredTrainings %}
|
||||
<li>
|
||||
{{ training.name }} absolviert
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p class="pb-4">
|
||||
Erfüllst du mehrere oder alle Voraussetzungen für diesen Einsatz?
|
||||
</p>
|
||||
<a href="{{ path('app_teamer_application', { 'uuid': assignment.uuid }) }}" class="btn">
|
||||
Hier bewerben!
|
||||
</a>
|
||||
{% include '_partials/_assignment_requirements_info.html.twig' %}
|
||||
{% if application is null %}
|
||||
<div class="pb-4">
|
||||
Erfüllst du mehrere oder alle Voraussetzungen für diesen Einsatz?
|
||||
</div>
|
||||
<div class="pb-4">
|
||||
<a href="{{ path('app_teamer_application_create', { 'uuid': assignment.uuid }) }}" class="btn">
|
||||
Hier bewerben!
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="pb-4">
|
||||
Du hast dich am {{ application.createdAt|date('d.m.Y') }} auf diesen Einsatz beworben.
|
||||
</div>
|
||||
<div class="pb-4">
|
||||
<button type="button"
|
||||
class="btn btn--secondary"
|
||||
title="Bewerbung zurückziehen"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du die Bewerbing wirklich zurückziehen?',
|
||||
'target-url': path('app_teamer_application_delete', { 'uuid': application.uuid })
|
||||
}) }}>
|
||||
Bewerbung zurückziehen
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if not isBookmarked %}
|
||||
<a href="{{ path('app_teamer_bookmark_toggle', { 'uuid': assignment.uuid, 'r': return_url() }) }}" class="underline">
|
||||
auf die Merkliste setzen
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user