feat: extend teamer dashboard

This commit is contained in:
Björn Fromme
2023-12-12 18:04:01 +01:00
parent 8ff59b3068
commit b5781df8d9
16 changed files with 286 additions and 30 deletions
@@ -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);
@@ -0,0 +1,25 @@
<?php
namespace App\Controller\Teamer;
use App\Entity\Feedback;
use App\Model\AjaxModalResponseDto;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class FeedbackController extends AbstractController
{
#[Route('/teamer/feedback/{uuid}', name: 'app_teamer_feedback')]
#[IsGranted('VIEW', subject: 'feedback')]
public function index(Feedback $feedback): JsonResponse
{
$response = new AjaxModalResponseDto();
$response->setContent($this->renderView('teamer/feedback/index.html.twig', [
'feedback' => $feedback,
]));
return $this->json($response);
}
}
+24
View File
@@ -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,
]);
}
}
+17 -1
View File
@@ -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;
}
}
+9
View File
@@ -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');
+4 -2
View File
@@ -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)
+14 -2
View File
@@ -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()
;
+21
View File
@@ -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()
;
}
}
+1
View File
@@ -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']),
+8
View File
@@ -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 '&Oslash; '.$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', [