<?php
namespace App\Controller\Front;
use JsonException;
use Exception;
use Throwable;
use App\Adapter\AuthAdapter;
use App\Controller\PageController;
use App\Form\AnonymousClientType;
use App\Model\Appointment;
use App\Model\Client;
use App\Model\Vehicle;
use App\Repository\MenuRepository;
use App\Service\AppointmentService;
use App\Service\SlotService;
use App\Service\ValidatorService;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
/**
* @Route("/appointment", priority="1", options={"expose"=true}, name="appointment_")
*/
class AppointmentController extends PageController
{
private LoggerInterface $logger;
private AppointmentService $appointmentService;
public function __construct(ManagerRegistry $doctrine, MenuRepository $menuRepository, LoggerInterface $oatLogger, AppointmentService $appointmentService)
{
parent::__construct($doctrine, $menuRepository);
$this->logger = $oatLogger;
$this->appointmentService = $appointmentService;
}
/**
* @Route("", name="index")
*/
public function index(Request $request): Response
{
$this->getPageByType('create-appointment');
$this->_initDatas($request);
$session = $request->getSession();
if (!$session->has('gon')) {
$session->set('gon', false);
}
// init session
if (!$session->get('appointment')) {
$session->set('appointment', new Appointment());
}
$reinit = 0;
if ($session->has('reinit')) {
$reinit = 1;
$session->remove('reinit');
}
$logout = 0;
if ($session->has('logout')) {
$logout = 1;
$session->remove('logout');
}
$needRegister = false;
if($this->isGranted('ROLE_CLIENT')) {
/** @var Client $user */
$user = $this->getUser();
$needRegister = $user->isInformationConfirmed();
}
return $this->render('front/appointment/index.html.twig', $this->getDatas([
'loggedUser' => $this->isGranted('ROLE_CLIENT'),
'needRegister' => $needRegister,
'reinit' => $reinit,
'logout' => $logout,
]));
}
/**
* @Route("/connexion", name="auth")
*
* @return Response
*/
public function connexion(AuthenticationUtils $authenticationUtils, Request $request, AuthAdapter $adapter): Response
{
return $this->forward('App\Controller\Front\SecurityController::auth', [$authenticationUtils, $request, $adapter, 'rdv' => AppointmentService::APPOINTMENT_SLUG]);
}
/**
* @Route("/profil", name="profil")
*
* @return RedirectResponse|Response
*
* @throws JsonException
*/
public function profil(Request $request, ValidatorService $validator, FormFactoryInterface $formFactory): Response
{
$this->_initDatas($request, 'anonymous-profil');
$client = new Client();
$form = $formFactory->createNamed('client', AnonymousClientType::class, $client);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$datas = $request->request->get('client')['login'];
$client->setEmail($datas['email']);
$this->addFlash('success', 'inscription1.confirmation');
/** @var Appointment $appointment */
$session = $request->getSession();
$appointment = $session->get('appointment');
$appointment->setClient($client);
$session->set('gon', true);
return $this->redirectToRoute('appointment_index');
}
}
$errors = $validator->getErrorsForm($form);
return $this->render(
'front/appointment/profil.html.twig',
$this->getDatas([
'clientForm' => $form->createView(),
'errors' => $errors,
])
);
}
/**
* @Route("/garages", name="garages", methods={"GET", "POST"})
*/
public function garages(Request $request, SerializerInterface $serializer): JsonResponse
{
try {
$session = $request->getSession();
$garages = $this->appointmentService->getGarages();
$session->set('garages', $garages);
/** @var Appointment $appointment */
$appointment = $session->get('appointment');
$currentStep = $request->query->get('currentStep', 1);
$maxStep = $request->query->get('maxStep', 1);
$session->set('maxStep', $maxStep);
$current = ($appointment) ? $appointment->getGarage() : null;
if ($request->isMethod('POST')) {
/** @var Appointment $appointment */
$appointment = $session->get('appointment');
$garageId = $request->request->get('garageId');
$garage = $this->appointmentService->getSelectedGarage($garages, $garageId);
if (!$garage) {
throw new Exception('location.not.found');
}
$appointment->setGarage($garage);
// reinit all futur step
$this->appointmentService->removeNextStep($appointment, 'garage');
$session->remove('vehicles');
return $this->json([
'success' => true,
'data' => $garage,
]);
}
return $this->json([
'success' => true,
'data' => [
'html' => $this->renderView('front/appointment/garages.html.twig', [
'maxStep' => $maxStep,
'currentStep' => $currentStep,
'garages' => $garages,
'current' => $current,
'appointment' => $appointment
]),
'garages' => $garages,
],
]);
} catch (Throwable $exception) {
$this->logger->error('GET GARAGE ERROR : '.$exception->getMessage());
return $this->json([
'error' => true,
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* @Route("/vehicle/{id}/save", name="vehicle_save", methods={"POST"})
*
* @ParamConverter("selectedVehicle", class="App\Model\Vehicle")
*
* @return void
*/
public function vehicle(Request $request, Vehicle $selectedVehicle): JsonResponse
{
$session = $request->getSession();
/** @var Appointment $appointment */
$appointment = $session->get('appointment');
$appointment->setVehicle($selectedVehicle);
// reinit all futur step
$this->appointmentService->removeNextStep($appointment, 'vehicle');
return $this->json([
'success' => true,
'vehicle' => $selectedVehicle,
]);
}
/**
* @Route("/service", name="service", methods={"POST", "GET"})
*/
public function service(Request $request): JsonResponse
{
$currentStep = $request->query->get('currentStep', 3);
$maxStep = $request->query->get('maxStep', 3);
$session = $request->getSession();
$session->set('maxStep', $maxStep);
/** @var Appointment $appointment */
$appointment = $session->get('appointment');
$data = [
'brand' => $appointment->getVehicle()->getBrand(),
'model' => $appointment->getVehicle()->getModel(),
'submodel' => $appointment->getVehicle()->getSubModel(),
'language' => $request->getLocale(),
];
$services = $this->appointmentService->getService($data);
/** @var array $ids */
$ids = $request->request->get('serviceIds', []);
if ($request->isMethod('POST')) {
$selectedServices = [];
foreach ($services as $service) {
if (in_array($service['id'], $ids, true)) {
$selectedServices[] = $service;
}
}
$appointment->setServices($selectedServices);
// reinit all futur step
$this->appointmentService->removeNextStep($appointment, 'service');
return $this->json([
'success' => true,
'services' => $ids,
]);
}
if ($rdvServices = $appointment->getServices()) {
foreach ($rdvServices as $service) {
$ids[] = $service['id'];
}
}
return $this->json([
'success' => true,
'data' => [
'html' => $this->renderView('front/appointment/service.html.twig', [
'maxStep' => $maxStep,
'currentStep' => $currentStep,
'services' => $services,
'current' => $appointment->getServices(),
'ids' => $ids,
'appointment' => $appointment
]),
],
]);
}
/**
* @Route("/availability", name="availability")
*/
public function availability(Request $request, SlotService $slotService): JsonResponse
{
$maxStep = $request->query->get('maxStep', 4);
$currentStep = $request->query->get('currentStep', 4);
$day = $request->get('day');
$time = $request->get('time');
$timeSlot = [
'day' => $day,
'time' => $time,
];
/** @var Appointment $appointment */
$session = $request->getSession();
$session->set('maxStep', $maxStep);
$appointment = $session->get('appointment');
if ($request->isMethod('POST')) { // save in Appointment
$receptionTime = $request->get('receptionTime');
$deliveryTime = $request->get('deliveryTime');
$receptionSlot = [
'reception' => $receptionTime,
'delivery' => $deliveryTime,
];
$slotService->saveSlots($appointment, $timeSlot, $receptionSlot);
return $this->json([
'success' => true,
]);
}
$responseDatas = [
'maxStep' => $maxStep,
'currentStep' => $currentStep,
];
$responseDatas = $slotService->handleRequest($request, $timeSlot, $responseDatas);
return $this->json([
'success' => true,
'data' => [
'html' => $this->renderView('front/appointment/availability.html.twig', $responseDatas),
'id' => $responseDatas['garageID'],
],
]);
}
/**
* @Route("/resume", name="resume")
*/
public function resume(Request $request): JsonResponse
{
$maxStep = $request->query->get('maxStep', 5);
$currentStep = $request->query->get('currentStep', 5);
$session = $request->getSession();
$session->set('maxStep', $maxStep);
/** @var Appointment $appointment */
$appointment = $session->get('appointment');
$this->appointmentService->getServiceHeaderInfo($appointment);
return $this->json([
'success' => true,
'data' => [
'html' => $this->renderView('front/appointment/resume.html.twig', [
'maxStep' => $maxStep,
'currentStep' => $currentStep,
'appointment' => $appointment
]),
],
]);
}
/**
* @Route("/payment", name="payment")
*
* @return void
*/
public function payment(Request $request): JsonResponse
{
$request->getSession()->set('maxStep', 6);
if ($request->isMethod('POST')) {
/** @var Appointment $appointment */
$appointment = $request->getSession()->get('appointment');
$appointment->setPaidOnline((bool) $request->request->get('payment'));
return $this->json([
'success' => true,
]);
}
return $this->json([
'data' => [
'html' => $this->renderView('front/appointment/payment.html.twig', []),
],
]);
}
/**
* @Route("/confirmation", name="confirmation", methods={"POST"})
*
* @throws JsonException
* @throws Throwable
* @throws ClientExceptionInterface
* @throws DecodingExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
public function confirmation(Request $request, AppointmentService $service): JsonResponse
{
/** @var Appointment $appointment */
$appointment = $request->getSession()->get('appointment');
$session = $request->getSession();
$user = $this->getUser();
$isUserConnected = $user && !$session->get('gon');
$this->appointmentService->sendAppointment($appointment, $isUserConnected);
$service->removeAllSession($session);
return $this->json([
'data' => [
'html' => $this->renderView('front/appointment/confirm_payment.html.twig', [
'appointment' => $appointment,
]),
],
]);
}
}