From b5781df8d9ad9f872d294a49326f485792f14101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Tue, 12 Dec 2023 18:04:01 +0100 Subject: [PATCH] feat: extend teamer dashboard --- migrations/Version20231212155746.php | 31 ++++++ .../Feedback/ProvideController.php | 5 +- src/Controller/Teamer/FeedbackController.php | 25 +++++ src/Controller/Teamer/IndexController.php | 24 +++++ src/Entity/Feedback.php | 18 +++- src/Repository/ApplicationRepository.php | 9 ++ src/Repository/AssignmentRepository.php | 6 +- src/Repository/DispositionRepository.php | 16 ++- src/Repository/FeedbackRepository.php | 21 ++++ src/Twig/AppExtension.php | 1 + src/Twig/AppRuntime.php | 8 ++ templates/admin/assignment/_form.html.twig | 1 - templates/admin/index.html.twig | 20 ++-- .../admin/teamer/recent_assignments.html.twig | 17 ++- templates/teamer/feedback/index.html.twig | 14 +++ templates/teamer/index.html.twig | 100 ++++++++++++++++-- 16 files changed, 286 insertions(+), 30 deletions(-) create mode 100644 migrations/Version20231212155746.php create mode 100644 src/Controller/Teamer/FeedbackController.php create mode 100644 templates/teamer/feedback/index.html.twig diff --git a/migrations/Version20231212155746.php b/migrations/Version20231212155746.php new file mode 100644 index 0000000..f55afd0 --- /dev/null +++ b/migrations/Version20231212155746.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE feedback ADD author VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE feedback DROP author'); + } +} diff --git a/src/Controller/HouseManager/Feedback/ProvideController.php b/src/Controller/HouseManager/Feedback/ProvideController.php index d8e9638..4aa0577 100644 --- a/src/Controller/HouseManager/Feedback/ProvideController.php +++ b/src/Controller/HouseManager/Feedback/ProvideController.php @@ -4,6 +4,7 @@ namespace App\Controller\HouseManager\Feedback; use App\Entity\Disposition; use App\Entity\Feedback; +use App\Entity\User; use App\Event\FeedbackProvidedEvent; use App\Form\FeedbackType; use Doctrine\ORM\EntityManagerInterface; @@ -28,6 +29,8 @@ class ProvideController extends AbstractController #[IsGranted('FEEDBACK', subject: 'disposition')] public function index(Disposition $disposition, Request $request): Response { + /** @var User $user */ + $user = $this->getUser(); $assignment = $disposition->getAssignment(); $destination = $assignment->getDestination(); @@ -42,7 +45,7 @@ class ProvideController extends AbstractController ->getFeedbackSet() ; - $feedback = new Feedback($assignment); + $feedback = new Feedback($assignment, $user); $form = $this->createForm(FeedbackType::class, $feedback, ['feedback_set' => $feedbackSet]); $form->handleRequest($request); diff --git a/src/Controller/Teamer/FeedbackController.php b/src/Controller/Teamer/FeedbackController.php new file mode 100644 index 0000000..7d28178 --- /dev/null +++ b/src/Controller/Teamer/FeedbackController.php @@ -0,0 +1,25 @@ +setContent($this->renderView('teamer/feedback/index.html.twig', [ + 'feedback' => $feedback, + ])); + + return $this->json($response); + } +} \ No newline at end of file diff --git a/src/Controller/Teamer/IndexController.php b/src/Controller/Teamer/IndexController.php index b6a0468..11de578 100644 --- a/src/Controller/Teamer/IndexController.php +++ b/src/Controller/Teamer/IndexController.php @@ -2,7 +2,10 @@ namespace App\Controller\Teamer; +use App\Entity\Application; use App\Entity\Assignment; +use App\Entity\Disposition; +use App\Entity\Feedback; use App\Entity\User; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -30,8 +33,29 @@ class IndexController extends AbstractController ->getNewMatchingTeamerProfile($teamer) ; + $recentFeedback = $this + ->entityManager + ->getRepository(Feedback::class) + ->getRecentForTeamer($teamer) + ; + + $pendingApplications = $this + ->entityManager + ->getRepository(Application::class) + ->getPendingForTeamer($teamer) + ; + + $upcomingDispositions = $this + ->entityManager + ->getRepository(Disposition::class) + ->getUpcomingDispositionsByTeamer($teamer) + ; + return $this->render('teamer/index.html.twig', [ 'matchingAssignments' => $matchingAssignments, + 'recentFeedback' => $recentFeedback, + 'pendingApplications' => $pendingApplications, + 'upcomingDispositions' => $upcomingDispositions, ]); } } \ No newline at end of file diff --git a/src/Entity/Feedback.php b/src/Entity/Feedback.php index 1af402c..eb2e6d7 100644 --- a/src/Entity/Feedback.php +++ b/src/Entity/Feedback.php @@ -56,12 +56,16 @@ class Feedback implements BlameableEntityInterface, TimestampableEntityInterface #[ORM\Column(type: Types::TEXT, nullable: true)] private ?string $commentInternal = null; - public function __construct(Assignment $assignment) + #[ORM\Column(length: 255)] + private ?string $author = null; + + public function __construct(Assignment $assignment, User $author) { $this->uuid = Uuid::v4(); $this->destinationName = $assignment->getDestination()->getProduct(); $this->assignmentDate = $assignment->getEffectiveDateFrom(); $this->jobProfileName = $assignment->getJobProfile()->getName(); + $this->author = $author->getFullName(); } public function getId(): ?int @@ -207,4 +211,16 @@ class Feedback implements BlameableEntityInterface, TimestampableEntityInterface return $this; } + + public function getAuthor(): ?string + { + return $this->author; + } + + public function setAuthor(string $author): static + { + $this->author = $author; + + return $this; + } } diff --git a/src/Repository/ApplicationRepository.php b/src/Repository/ApplicationRepository.php index 5efb83d..85a498f 100644 --- a/src/Repository/ApplicationRepository.php +++ b/src/Repository/ApplicationRepository.php @@ -55,6 +55,15 @@ class ApplicationRepository extends ServiceEntityRepository ; } + public function getPendingForTeamer(Teamer $teamer, int $limit = 5): array + { + return $this + ->getPendingForTeamerQuery($teamer) + ->setMaxResults($limit) + ->getResult() + ; + } + public function getCurrentByAssignment(Assignment $assignment): array { $qb = $this->createQueryBuilder('application'); diff --git a/src/Repository/AssignmentRepository.php b/src/Repository/AssignmentRepository.php index 635a3e0..845ecf9 100644 --- a/src/Repository/AssignmentRepository.php +++ b/src/Repository/AssignmentRepository.php @@ -221,10 +221,12 @@ class AssignmentRepository extends ServiceEntityRepository ->select('assignment', 'destination', 'job_profile') ->innerJoin('assignment.destination', 'destination') ->innerJoin('assignment.jobProfile', 'job_profile') - ->leftJoin('assignment.applications', 'application', Join::WITH, $qb->expr()->neq('application.teamer', ':teamer')) + ->leftJoin('assignment.applications', 'application', Join::WITH, $qb->expr()->eq('application.teamer', ':teamer')) + ->leftJoin('assignment.dispositions', 'disposition', Join::WITH, $qb->expr()->eq('disposition.teamer', ':teamer')) ->where($qb->expr()->andX( $qb->expr()->in('assignment.jobProfile', ':jobProfiles'), - $qb->expr()->isNull('application') + $qb->expr()->isNull('application'), + $qb->expr()->isNull('disposition') )) ->setParameter('jobProfiles', $teamer->getJobProfiles()) ->setParameter('teamer', $teamer) diff --git a/src/Repository/DispositionRepository.php b/src/Repository/DispositionRepository.php index 00c1aac..9d8c6ca 100644 --- a/src/Repository/DispositionRepository.php +++ b/src/Repository/DispositionRepository.php @@ -29,8 +29,9 @@ class DispositionRepository extends ServiceEntityRepository $qb = $this->createQueryBuilder('disposition'); return $qb - ->select('disposition', 'assignment', 'job_profile', 'destination') + ->select('disposition', 'assignment', 'job_profile', 'destination', 'documents') ->innerJoin('disposition.assignment', 'assignment') + ->leftJoin('assignment.documents', 'documents') ->innerJoin('assignment.jobProfile', 'job_profile') ->innerJoin('assignment.destination', 'destination') ->where($qb->expr()->andX( @@ -52,6 +53,15 @@ class DispositionRepository extends ServiceEntityRepository ; } + public function getUpcomingDispositionsByTeamer(Teamer $teamer, int $limit = 5): array + { + return $this + ->getUpcomingDispositionsByTeamerQuery($teamer) + ->setMaxResults($limit) + ->getResult() + ; + } + public function getRecentDispositionsByTeamerQuery(Teamer $teamer): Query { $qb = $this->createQueryBuilder('disposition'); @@ -123,10 +133,12 @@ class DispositionRepository extends ServiceEntityRepository ->innerJoin('assignment.destination', 'destination') ->where($qb->expr()->andX( $qb->expr()->in('destination.hotelBusProId', ':hotelBusProIds'), - $qb->expr()->lt('destination.dateTo', ':dateTo') + $qb->expr()->lt('destination.dateTo', ':dateTo'), + $qb->expr()->eq('disposition.status', ':status') )) ->setParameter('hotelBusProIds', $hotelBusProIds) ->setParameter('dateTo', new \DateTimeImmutable()) + ->setParameter('status', Disposition::STATUS_NEW) ->getQuery() ->getResult() ; diff --git a/src/Repository/FeedbackRepository.php b/src/Repository/FeedbackRepository.php index aff79ed..3f97db0 100644 --- a/src/Repository/FeedbackRepository.php +++ b/src/Repository/FeedbackRepository.php @@ -3,6 +3,7 @@ namespace App\Repository; use App\Entity\Feedback; +use App\Entity\Teamer; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; @@ -28,6 +29,8 @@ class FeedbackRepository extends ServiceEntityRepository return $qb ->select('feedback', 'teamer') ->innerJoin('feedback.teamer', 'teamer') + ->where($qb->expr()->eq('feedback.status', ':status')) + ->setParameter('status', Feedback::STATUS_NEW) ->orderBy('feedback.createdAt', 'DESC') ->setMaxResults($limit) ->getQuery() @@ -47,4 +50,22 @@ class FeedbackRepository extends ServiceEntityRepository ->getSingleScalarResult() ; } + + public function getRecentForTeamer(Teamer $teamer, int $limit = 5): array + { + $qb = $this->createQueryBuilder('feedback'); + + return $qb + ->where($qb->expr()->andX( + $qb->expr()->eq('feedback.teamer', ':teamer'), + $qb->expr()->eq('feedback.status', ':status') + )) + ->setParameter('teamer', $teamer) + ->setParameter('status', Feedback::STATUS_PUBLISHED) + ->orderBy('feedback.createdAt', 'DESC') + ->setMaxResults($limit) + ->getQuery() + ->getResult() + ; + } } diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 73cbe45..291b6c2 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -16,6 +16,7 @@ class AppExtension extends AbstractExtension new TwigFilter('file_icon', [AppRuntime::class, 'fileIconFilter'], ['is_safe' => ['html']]), new TwigFilter('date_diff', [AppRuntime::class, 'dateDiffForHumans']), new TwigFilter('format_money', [AppRuntime::class, 'formatMoney']), + new TwigFilter('format_rating', [AppRuntime::class, 'formatRating'], ['is_safe' => ['html']]), new TwigFilter('license_label', [AppRuntime::class, 'licenseLabel']), new TwigFilter('teamer_status_label', [AppRuntime::class, 'teamerStatusLabel']), new TwigFilter('bpn_country_label', [AppRuntime::class, 'bpnCountryLabel']), diff --git a/src/Twig/AppRuntime.php b/src/Twig/AppRuntime.php index 0b3d288..33e0b04 100644 --- a/src/Twig/AppRuntime.php +++ b/src/Twig/AppRuntime.php @@ -89,6 +89,14 @@ class AppRuntime implements RuntimeExtensionInterface return $this->intlExtension->formatCurrency($amount, 'EUR'); } + public function formatRating(int $rating): string + { + // Ratings are stored as integers so divide by 100 first + $rating = $rating / 100; + + return 'Ø '.$this->intlExtension->formatNumber($rating, ['fraction_digit' => 2]); + } + public function renderIcon(Environment $environment, string $icon, string $classes = 'w-5 h-5'): string { return $environment->render('_partials/_icon.html.twig', [ diff --git a/templates/admin/assignment/_form.html.twig b/templates/admin/assignment/_form.html.twig index b7452ff..ebf22b1 100644 --- a/templates/admin/assignment/_form.html.twig +++ b/templates/admin/assignment/_form.html.twig @@ -16,7 +16,6 @@
{{ form_row(form.destination) }}
- {{ form_row(form.status) }} {{ form_row(form.availableDispositions) }}

diff --git a/templates/admin/index.html.twig b/templates/admin/index.html.twig index d1a60be..7780974 100644 --- a/templates/admin/index.html.twig +++ b/templates/admin/index.html.twig @@ -3,12 +3,14 @@ {% block content %}
-

+

Neue Bewerbungen

-

- {{ newApplicationsCount }} neu, {{ pendingApplicationsCount }} in Bearbeitung -

+ {% if newApplicationsCount > 0 or pendingApplicationsCount > 0 %} +

+ {{ newApplicationsCount }} neu, {{ pendingApplicationsCount }} in Bearbeitung +

+ {% endif %}
    {% for application in applications %} {% set assignment = application.assignment %} @@ -32,12 +34,14 @@
-

+

Neue Dokumente

-

- {{ newDocumentsCount }} neu {{ pendingDocumentsCount }} in Bearbeitung -

+ {% if newDocumentsCount > 0 or pendingDocumentsCount > 0 %} +

+ {{ newDocumentsCount }} neu {{ pendingDocumentsCount }} in Bearbeitung +

+ {% endif %}