src/Controller/DashboardController.php line 55

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Consultation;
  4. use App\Form\SupportType;
  5. use App\Repository\ConsultationRepository;
  6. use App\Repository\PatientRepository;
  7. use App\Repository\UserRepository;
  8. use App\Security\AccessChecker as SecurityAccessChecker;
  9. use App\Security\AccessChecker;
  10. use App\Service\Subscription;
  11. use App\Service\UserData;
  12. use Doctrine\ORM\EntityManager;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Doctrine\Persistence\ManagerRegistry;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\String\Slugger\SluggerInterface;
  20. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  21. use Symfony\Component\HttpFoundation\File\UploadedFile;
  22. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  23. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  24. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  25. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  26. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  27. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  28. use Symfony\Component\HttpFoundation\JsonResponse;
  29. use Symfony\Component\Mailer\MailerInterface;
  30. use Symfony\Component\Mime\Address;
  31. use Symfony\Component\Mime\Email;
  32. use Symfony\Component\Routing\Generator\UrlGenerator;
  33. class DashboardController extends AbstractController
  34. {
  35.   private $doctrine;
  36.   private $subscription;
  37.   private $patientRepository;
  38.   private $accessChecker;
  39.   private $em;
  40.   public function __construct(ManagerRegistry $doctrineSubscription $subscriptionPatientRepository $patientRepositoryEntityManagerInterface $emSecurityAccessChecker $accessChecker)
  41.   {
  42.     $this->doctrine $doctrine;
  43.     $this->subscription $subscription;
  44.     $this->patientRepository $patientRepository;
  45.     $this->em $em;
  46.     $this->accessChecker $accessChecker;
  47.   }
  48.   /**
  49.    * @Route("/", name="dashboard_index")
  50.    */
  51.   public function index(UserRepository $userRepositoryConsultationRepository $consultationRepository): Response
  52.   {
  53.     if ($this->accessChecker->isPatient()) return $this->redirectToRoute("dashboard_index_patient");
  54.     if (!$this->accessChecker->isAdmin() && !$this->accessChecker->isSubscribed()) return $this->redirectToRoute("subscription");
  55.     if (!$this->accessChecker->isCustomer() && !$this->accessChecker->isAdmin()) return $this->redirectToRoute("dashboard_index_patient");
  56.     $now = new \DateTimeImmutable();
  57.     $start $now->modify("last month");
  58.     $end $now;
  59.     $datas $this->forward('App\Controller\DashboardController::chart', [], ["start" => $start->format('Y-m-d'), "end" => $end->format('Y-m-d')]);
  60.     $datas json_decode($datas->getContent(), true);
  61.     $actifsPatients $datas end($datas['series'][0]["data"]) : 0;
  62.     $nouveauxPatients $datas end($datas['series'][1]["data"]) : 0;
  63.     $inactifsPatients $datas end($datas['series'][2]["data"]) : 0;
  64.     // dd($datas, $nouveauxPatients, $inactifsPatients, $actifsPatients);
  65.     return $this->render('dashboard/index.html.twig', [
  66.       'user' => $this->getUser(),
  67.       "actifsPatients" => $actifsPatients,
  68.       "inactifsPatients" => $inactifsPatients,
  69.       'nouveauxPatients' => $nouveauxPatients
  70.     ]);
  71.   }
  72.   /**
  73.    * @Route("/suivi", name="dashboard_index_patient")
  74.    */
  75.   public function patientIndex(UserRepository $userRepositoryUserData $userData): Response
  76.   {
  77.     $user $this->getUser();
  78.     if (!$this->accessChecker->isPatient() && $this->accessChecker->isCustomer() && !$this->accessChecker->isAdmin()) return $this->redirectToRoute("dashboard_index");
  79.     $chart = [
  80.       'series' => array_values($userData->getProfils($this->getUser())),
  81.       'categories' => array_keys($userData->getProfils($this->getUser())),
  82.       'colors' => ['#ffaa43'"#9fbf7e""#ffff99""#a6a6a6""#cddebc""#ffcb8b""#d9d9d9""#f3f3f3"],
  83.       'tcolors' => ['#ffb965'"#aec993""#ffffc5""#b5b5b5""#dce8d0""#ffdaab""#e8e8e8""#f3f3f3"],
  84.       'tdescriptions' => ['(protéines, lipides, glucides)'"(sport, hydratation, stress, sommeil...)""(troubles et pathologies en lien avec la nutrition)""(comportement alimentaire)""(flore intestinale)""(vitamines, minéraux et oligoéléments)""(neurotransmetteurs)"""]
  85.     ];
  86.     return $this->render('dashboard/suivi.html.twig', [
  87.       'user' => $this->getUser(),
  88.       'chart' => $chart
  89.     ]);
  90.   }
  91.   /**
  92.    * @Route("/dashboard/data2", name="dashboard_chart2")
  93.    */
  94.   public function chart(Request $requestUserRepository $userRepository): Response
  95.   {
  96.     // if (!$this->accessChecker->isAdmin()) return $this->redirectToRoute("dashboard_index");
  97.     if (!$this->accessChecker->isSubscribed()) return $this->redirectToRoute("subscription");
  98.     $start $request->request->get('start') ? $request->request->get('start') : $request->query->get('start');
  99.     $end $request->request->get('end') ? $request->request->get('end') : $request->query->get('end');
  100.     $patients $userRepository->getPatients($this->getUser());
  101.     $weeks $this->getWeeksOfMonthWithStartAndEndDates($start$end);
  102.     $result = array();
  103.     foreach ($weeks as $week) {
  104.       $weekStart = new \DateTimeImmutable($week["start"]);
  105.       $weekEnd = new \DateTimeImmutable($week["end"]);
  106.       $result[$week["label"]]["Patients actifs"] = 0;
  107.       $result[$week["label"]]["Nouveaux patients"] = 0;
  108.       $result[$week["label"]]["Patients archivés"] = 0;
  109.       if ($weekStart > new \DateTimeImmutable()) continue;
  110.       $patientsActifs = [];
  111.       foreach ($patients as $patient) {
  112.         $patientLastConsultation $this->em->getRepository(Consultation::class)->findOneBy(["patient" => $patient], ["date" => "desc"]);
  113.         $dateCreated $patient->getCreatedAt();
  114.         if ($patientLastConsultation) {
  115.           $dateLastConsultation =  $patientLastConsultation->getDate();
  116.         } else {
  117.           $dateLastConsultation NULL;
  118.         }
  119.         $checkNewUser $this->daysBetweenDates($weekStart$dateCreated);
  120.         if ($checkNewUser >= &&  $checkNewUser 7) {
  121.           $result[$week["label"]]["Nouveaux patients"] += 1;
  122.           if (!in_array($patient->getId(), $patientsActifs)) {
  123.             $result[$week["label"]]["Patients actifs"] += 1;
  124.             $patientsActifs[] = $patient->getId();
  125.           }
  126.         }
  127.         if ($dateLastConsultation) {
  128.           $checkArchiveUser $this->daysBetweenDates($weekStart$dateLastConsultation);
  129.           if ($checkArchiveUser >= 170 &&  $checkArchiveUser 180) {
  130.             $result[$week["label"]]["Patients archivés"] += 1;
  131.           } elseif ($dateCreated <= $weekStart && !in_array($patient->getId(), $patientsActifs)) {
  132.             $result[$week["label"]]["Patients actifs"] += 1;
  133.             $patientsActifs[] = $patient->getId();
  134.           }
  135.         } elseif ($dateCreated <= $weekStart && !in_array($patient->getId(), $patientsActifs)) {
  136.           $result[$week["label"]]["Patients actifs"] += 1;
  137.           $patientsActifs[] = $patient->getId();
  138.         }
  139.       }
  140.     }
  141.     $series[0]["name"] = "Patients actifs";
  142.     $series[1]["name"] = "Nouveaux patients";
  143.     $series[2]["name"] = "Patients archivés";
  144.     $categories = array();
  145.     foreach ($result as $s => $r) {
  146.       $categories[] = $s;
  147.       $series[0]["data"][] = $r["Patients actifs"];
  148.       $series[1]["data"][] = $r["Nouveaux patients"];
  149.       $series[2]["data"][] = $r["Patients archivés"];
  150.     }
  151.     return $this->json(["series" => $series"categories" => $categories]);
  152.   }
  153.   private function daysBetweenDates($datetime2$datetime1)
  154.   {
  155.     $interval $datetime1->diff($datetime2);
  156.     $sign = ($datetime1 $datetime2) ? -1;
  157.     return $sign $interval->days;
  158.   }
  159.   private function getWeeksOfMonthWithStartAndEndDates($start null$end null)
  160.   {
  161.     // Définir les dates de début et de fin si elles ne sont pas fournies
  162.     $startDate $start strtotime($start) : strtotime(date("Y-m-01"));
  163.     $endDate $end strtotime($end) : strtotime(date("Y-m-t"));
  164.     // Vérification que $start est avant $end
  165.     if ($startDate $endDate) {
  166.       throw new \InvalidArgumentException("La date de début doit être antérieure ou égale à la date de fin.");
  167.     }
  168.     $weeks = [];
  169.     // Boucle à travers les jours entre $startDate et $endDate
  170.     for ($currentDate $startDate$currentDate <= $endDate$currentDate strtotime('+1 day'$currentDate)) {
  171.       $week_number date("W"$currentDate);
  172.       if (!array_key_exists($week_number$weeks)) {
  173.         $weeks[$week_number] = [
  174.           'start' => $currentDate,
  175.           'end' => $currentDate
  176.         ];
  177.       } else {
  178.         $weeks[$week_number]['end'] = $currentDate;
  179.       }
  180.     }
  181.     // Formater les dates et ajouter les labels
  182.     foreach ($weeks as $week_number => $dates) {
  183.       $weeks[$week_number]['start'] = date("Y-m-d"$dates['start']);
  184.       $weeks[$week_number]['end'] = date("Y-m-d"$dates['end']);
  185.       $weeks[$week_number]['label'] = "Semaine " date("W"$dates['start']);
  186.     }
  187.     return $weeks;
  188.   }
  189.   /**
  190.    * @Route("/dashboard/data", name="dashboard_chart")
  191.    */
  192.   public function chart2(Request $requestConsultationRepository $consultationRepositoryUserRepository $userRepository): Response
  193.   {
  194.     // if (!$this->accessChecker->isAdmin()) return $this->redirectToRoute("dashboard_index");
  195.     if (!$this->accessChecker->isSubscribed()) return $this->redirectToRoute("subscription");
  196.     $start $request->request->get('start') ? $request->request->get('start') : $request->query->get('start');
  197.     $end $request->request->get('end') ? $request->request->get('end') : $request->query->get('end');
  198.     $start = new \DateTimeImmutable($start);
  199.     $end = new \DateTimeImmutable($end);
  200.     $categories = [];
  201.     $series = [
  202.       [
  203.         "name" => "Nouveaux patients",
  204.         "data" => []
  205.       ],
  206.       [
  207.         "name" => "Patients actifs",
  208.         "data" => []
  209.       ],
  210.       [
  211.         "name" => "Patients archivés",
  212.         "data" => []
  213.       ],
  214.     ];
  215.     $currentDate = new \DateTime($start->format('Y-m-d'));
  216.     $nextDate = new \DateTime($start->format('Y-m-d'));
  217.     $i 0;
  218.     while ($currentDate <= $end) {
  219.       $i++;
  220.       $nextDate->modify('+1 week');
  221.       $old_date = new \DateTimeImmutable("2020-01-01");
  222.       $patients $userRepository->findNewPatientsBetweenDates($old_date$nextDate$this->getUser());
  223.       // nouveaux patients
  224.       $nouveauxPatients $userRepository->findNewPatientsBetweenDates($currentDate$nextDate$this->getUser());
  225.       $series[0]["data"][] = count($nouveauxPatients);
  226.       // patients actifs/inactifs
  227.       $inactifsPatients 0;
  228.       $actifsPatients 0;
  229.       foreach ($patients as $patient) {
  230.         $_currentDate = new \DateTimeImmutable($currentDate->format('Y-m-d'));
  231.         $_nextDate = new \DateTimeImmutable($nextDate->format('Y-m-d'));
  232.         if ($_currentDate > new \DateTimeImmutable()) {
  233.           continue;  // Ignore la semaine qui est dans le futur
  234.         }
  235.         $_start $_currentDate->modify("-180 days");
  236.         $_end $_nextDate->modify("-180 days");
  237.         $lastConsultations array_merge(
  238.           $consultationRepository->findBetweenDates($_start$_currentDate, [$patient]),
  239.           $consultationRepository->findBetweenDates($_end$_nextDate, [$patient])
  240.         );
  241.         // Vérifie si le patient n'a pas de consultations dans les 180 derniers jours
  242.         if (empty($lastConsultations)) {
  243.           $inactifsPatients += 1;
  244.         } else {
  245.           $actifsPatients += 1;
  246.         }
  247.       }
  248.       $series[1]["data"][] = $actifsPatients;
  249.       $series[2]["data"][] = $inactifsPatients;
  250.       $categories[] = "Semaine " $currentDate->format('W');
  251.       $currentDate = clone $nextDate;
  252.     }
  253.     return $this->json(["series" => $series"categories" => $categories]);
  254.   }
  255.   private function formatDatas(array $consultations, array $patients\DateTime $start\DateTime $end): array
  256.   {
  257.     // Crée un tableau pour les résultats des consultations et des autres entités
  258.     $consultationsData = [];
  259.     $consultationsCategories = [];
  260.     $patientsData = [];
  261.     $patientCategories = [];
  262.     $archivedPatientsData = [];
  263.     $archivedPatientsCategories = [];
  264.     // Initialise la date en cours avec la date de début
  265.     $currentDate = clone $start;
  266.     // Tant que la date en cours est inférieure ou égale à la date de fin, on continue
  267.     while ($currentDate <= $end) {
  268.       $yearWeek $currentDate->format('o-W'); // o: année ISO-8601, W: numéro de semaine ISO-8601
  269.       $consultationsCategories[] = $currentDate->format('W');
  270.       // Compte le nombre de consultations pour chaque semaine
  271.       if (!isset($consultationsData[$yearWeek])) {
  272.         $consultationsData[$yearWeek] = 0;
  273.       }
  274.       foreach ($consultations as $consultation) {
  275.         $consultationYearWeek $consultation->getDate()->format('o-W');
  276.         if ($consultationYearWeek === $yearWeek) {
  277.           $consultationsData[$yearWeek]++;
  278.         }
  279.       }
  280.       // Compte le nombre de consultations créées pour chaque semaine
  281.       if (!isset($patientsData[$yearWeek])) {
  282.         $patientsData[$yearWeek] = 0;
  283.       }
  284.       if (!isset($archivedPatientsData[$yearWeek])) {
  285.         $archivedPatientsData[$yearWeek] = 0;
  286.       }
  287.       foreach ($patients as $patient) {
  288.         $entityYearWeek $patient->getCreatedAt()->format('o-W');
  289.         $patientCategories[] = $patient->getCreatedAt()->format('W');
  290.         if ($entityYearWeek === $yearWeek) {
  291.           $patientsData[$yearWeek]++;
  292.         }
  293.         // compte les patients inactifs (dernière consultation > 180j par rapport a la semaine en cours)
  294.         $patientConsultations $this->em->getRepository(Consultation::class)->findBy(["patient" => $patient], ["date" => "ASC"]);
  295.         $lastConsultation null;
  296.         foreach ($patientConsultations as $patientConsultation) {
  297.           if (!$lastConsultation$lastConsultation $patientConsultation;
  298.           else {
  299.             if ($patientConsultation->getDate() > $lastConsultation->getDate() && $lastConsultation->getDate()->format("o-W") <= $yearWeek) {
  300.               $lastConsultation $patientConsultation;
  301.             }
  302.           }
  303.         }
  304.         if ($lastConsultation) {
  305.           $consultationDate $lastConsultation->getDate();
  306.           $consultation180DaysAfter = (clone $consultationDate)->modify("+180 days")->format("o-W");
  307.           if ($consultation180DaysAfter === $yearWeek) {
  308.             if ($archivedPatientsData[$consultation180DaysAfter] >= 0) {
  309.               $archivedPatientsData[$consultation180DaysAfter]++;
  310.               $archivedPatientsCategories[] = $lastConsultation->getDate()->format('W');
  311.             }
  312.           }
  313.         }
  314.       }
  315.       // Passe à la semaine suivante
  316.       $currentDate->modify('+1 week');
  317.     }
  318.     // Retourne un tableau avec les résultats des consultations et des autres entités
  319.     return [[array_values($consultationsData), $consultationsCategories], [array_values($patientsData), $patientCategories], [array_values($archivedPatientsData), $archivedPatientsCategories]];
  320.   }
  321.   /**
  322.    * @Route("/support", name="support")
  323.    */
  324.   public function support(Request $requestMailerInterface $mailerUserRepository $userRepository)
  325.   {
  326.     $data = [];
  327.     $form $this->createForm(SupportType::class, $data);
  328.     $form->handleRequest($request);
  329.     if ($form->isSubmitted() && $form->isValid()) {
  330.       $datas $request->request->all()['support'];
  331.       $message $datas['message'];
  332.       $answer $datas['answer'];
  333.       $email $this->getUser()->getEmail();
  334.       $admins $userRepository->findBy(array("medecin" => null));
  335.       $adminEmails = [];
  336.       // foreach ($admins as $a) {
  337.       //   $adminEmails[] = $a->getEmail();
  338.       // }
  339.       $adminEmails[] = 'support@profil-diet.com';
  340.       $link $this->generateUrl('user_index', [], UrlGeneratorInterface::ABSOLUTE_URL) . "?userId=" $this->getUser()->getId();
  341.       $mail = (new Email())
  342.         ->subject('Nouvelle demande du support technique')
  343.         ->from(new Address($email))
  344.         ->to(...$adminEmails)
  345.         ->html($this->renderView('email/support.html.twig', ["user" => $this->getUser(), "message" => $message"answer" => $answer"link" => $link]));
  346.       $guideUrl $this->generateUrl("aide", [], UrlGenerator::ABSOLUTE_URL);
  347.       $faqUrl $this->generateUrl("faq", [], UrlGenerator::ABSOLUTE_URL);
  348.       $urls = array(
  349.         "faq" => $faqUrl,
  350.         "pdf" => $guideUrl
  351.       );
  352.       $answerMail = (new Email())
  353.         ->subject('PROFIL-DIET : vous avez contacté le support technique')
  354.         ->from(new Address($_ENV['MAILER_ADDRESS'], $_ENV['MAILER_NAME']))
  355.         ->to(new Address($email))
  356.         ->html($this->renderView('email/support_reponse.html.twig', ["user" => $this->getUser(), "urls" => $urls]));
  357.       $mailer->send($mail);
  358.       $mailer->send($answerMail);
  359.       $session $request->getSession();
  360.       $session->getFlashBag()->add('success'"Nous avons bien reçu votre demande. Le support technique vous répondra sous 24h ouvrables. <br />
  361.       Vous pouvez aussi consulter notre <a class='text-decoration-underline color-inherit' href='" $faqUrl "'>FAQ</a> (Foire Aux Questions) ou le guide PDF (<a class='text-decoration-underline color-inherit' href='" $guideUrl "'>ici</a>).<br /><br />
  362.       
  363.       À bientôt,<br />
  364.       La Team Profil-diet");
  365.     }
  366.     // Réponse AJAX
  367.     if ($form->isSubmitted() && !$form->isValid()) {
  368.       return new Response($this->json($formResponse::HTTP_BAD_REQUEST));
  369.     }
  370.     return $this->render('support/index.html.twig', [
  371.       'form' => $form->createView(),
  372.     ]);
  373.   }
  374.   /**
  375.    * @Route("/tutos", name="tutos")
  376.    */
  377.   public function tutos(Request $requestMailerInterface $mailerUserRepository $userRepository)
  378.   {
  379.     return $this->render('tutos/index.html.twig');
  380.   }
  381.   /**
  382.    * @Route("/aide", name="aide")
  383.    */
  384.   public function help()
  385.   {
  386.     $filename "guide-utilisation-profil-diet.pdf";
  387.     $dir $this->getParameter('kernel.project_dir') . '/public/docs/';
  388.     $pdfPath $dir $filename;
  389.     if (!file_exists($pdfPath)) {
  390.       throw $this->createNotFoundException('Le fichier PDF demandé n\'existe pas.');
  391.     }
  392.     $response = new BinaryFileResponse($pdfPath);
  393.     $response->headers->set('Content-Type''application/pdf');
  394.     $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT"Guide d'utilisation Profil-diet.pdf");
  395.     return $response;
  396.   }
  397.   /**
  398.    * @Route("/cgu", name="cgu")
  399.    */
  400.   public function cgu(Request $request)
  401.   {
  402.     $filename 'cgu.pdf';
  403.     $dir $this->getParameter('kernel.project_dir') . '/public/uploads/documents/';
  404.     $pdf file_get_contents($dir $filename);
  405.     return new Response($pdf200, [
  406.       'Content-Type' => 'application/pdf',
  407.       'Content-Disposition' => 'inline; filename="file.pdf"'
  408.     ]);
  409.   }
  410.   /**
  411.    * @Route("/rgpd", name="rgpd")
  412.    */
  413.   public function rgpd(Request $request)
  414.   {
  415.     $filename 'rgpd.pdf';
  416.     $dir $this->getParameter('kernel.project_dir') . '/public/uploads/documents/';
  417.     $pdf file_get_contents($dir $filename);
  418.     return new Response($pdf200, [
  419.       'Content-Type' => 'application/pdf',
  420.       'Content-Disposition' => 'inline; filename="file.pdf"'
  421.     ]);
  422.   }
  423. }