From 7e5b0e66c483818d79a02a622e145b53d559c120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Fri, 1 Mar 2024 13:50:54 +0100 Subject: [PATCH] feat: dashboard for role 'manager' --- src/Controller/Manager/IndexController.php | 34 ++++- src/Entity/Assignment.php | 1 + src/Repository/AssignmentRepository.php | 3 + templates/manager/index.html.twig | 140 +++++++++++++++++++++ 4 files changed, 175 insertions(+), 3 deletions(-) diff --git a/src/Controller/Manager/IndexController.php b/src/Controller/Manager/IndexController.php index 5300be9..277d5ba 100644 --- a/src/Controller/Manager/IndexController.php +++ b/src/Controller/Manager/IndexController.php @@ -2,17 +2,45 @@ namespace App\Controller\Manager; +use App\Entity\Assignment; +use App\Model\AssignmentFilterDto; +use App\Repository\AssignmentRepository; +use Knp\Component\Pager\PaginatorInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class IndexController extends AbstractController { - #[Route('/management', name: 'app_manager_index')] - public function index(): Response + public function __construct(private readonly AssignmentRepository $assignmentRepository, private readonly PaginatorInterface $paginator) { - return $this->render('manager/index.html.twig', [ + } + #[Route('/management', name: 'app_manager_index')] + public function index(Request $request): Response + { + $filterDto = new AssignmentFilterDto(); + $filterDto->setStatus(Assignment::STATUS_UNSTAFFED); + + $query = $this + ->assignmentRepository + ->getListQuery($filterDto) + ; + + $pagination = $this->paginator->paginate( + $query, + $request->query->getInt('page', 1), + 10, + [ + 'wrap-queries' => true, // Required for query with 'having' clause + 'defaultSortFieldName' => 'destination.dateFrom', + 'defaultSortDirection' => 'desc', + ] + ); + + return $this->render('manager/index.html.twig', [ + 'pagination' => $pagination, ]); } } \ No newline at end of file diff --git a/src/Entity/Assignment.php b/src/Entity/Assignment.php index ca17557..30eb21f 100644 --- a/src/Entity/Assignment.php +++ b/src/Entity/Assignment.php @@ -28,6 +28,7 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa public const STATUS_STAFFED = 'staffed'; public const STATUS_PARTLY_STAFFED = 'partly_staffed'; public const STATUS_STAFFING = 'staffing'; + public const STATUS_UNSTAFFED = 'unstaffed'; #[ORM\Id] #[ORM\GeneratedValue] diff --git a/src/Repository/AssignmentRepository.php b/src/Repository/AssignmentRepository.php index b8b5e33..1fe5510 100644 --- a/src/Repository/AssignmentRepository.php +++ b/src/Repository/AssignmentRepository.php @@ -97,6 +97,9 @@ class AssignmentRepository extends ServiceEntityRepository ->andHaving('COUNT(application.id) > 0') ; break; + case Assignment::STATUS_UNSTAFFED: + $qb->having('assignment.availableDispositions > COUNT(disposition.id)'); + break; } } diff --git a/templates/manager/index.html.twig b/templates/manager/index.html.twig index 7b6109e..1a9dc47 100644 --- a/templates/manager/index.html.twig +++ b/templates/manager/index.html.twig @@ -1,4 +1,144 @@ {% extends 'manager/layout.html.twig' %} +{% block title %}Offene Einsätze{% endblock %} + {% block content %} +
+

+ Offene Einsätze +

+
+ +
+
+ + + + + + + + + + + + + + {% for assignment in pagination %} + + + + + + + + + + {% else %} + + + + {% endfor %} + +
+ Status + + {{ knp_pagination_sortable(pagination, 'Einsatz­zeitraum', 'destination.dateFrom') }} + + {{ knp_pagination_sortable(pagination, 'Destination', 'destination.product') }} + + {{ knp_pagination_sortable(pagination, 'Jobprofil', 'job_profile.name') }} + + {{ knp_pagination_sortable(pagination, 'Bus', 'assignment.pickup') }} + + Einteilungen +
+
+ {% if assignment.status == 'draft' %} + + + + {{ icon('edit', 'w-4 h-4') }} + {% else %} + {% if assignment.staffed %} + + + + {% elseif assignment.partlyStaffed %} + + + + {% elseif assignment.staffing %} + + + + {% else %} + + + + {% endif %} + {% if assignment.status == 'closed' %} + {{ icon('locked', 'w-4 h-4 text-red-500') }} + {% else %} + {{ icon('unlocked', 'w-4 h-4') }} + {% endif %} + {% endif %} +
+
+ + {{ assignment.effectivePeriod.start|date('d.m.Y') }} - +
+ {{ assignment.effectivePeriod.end|date('d.m.Y') }} +
+
+ + {{ icon('flag-' ~ assignment.destination.country, 'w-5 h-5 shrink-0') }} +
+ {{ assignment.destination.hotel }} +
+
+
+ + {{ assignment.jobProfile.name }} + + + {% if assignment.pickup %} + {% set pickup = assignment.destination.pickup(assignment.pickup) %} + {% if pickup %} + + ab {{ pickup.city }} +
+ {{ pickup.time }} +
+ {% else %} + ungültiger Zustieg + {% endif %} + {% else %} + - + {% endif %} +
+ {{ assignment.dispositions|length }}/{{ assignment.availableDispositions }} +
    + {% for disposition in assignment.dispositions %} +
  • +
    + {{ disposition.teamer }} + +
    +
  • + {% endfor %} +
+
+
+ Keine Daten... +
+ {{ knp_pagination_render(pagination) }} +
+
{% endblock %} \ No newline at end of file