<?php
namespace App\Controller;
use App\Entity\Atouts;
use App\Entity\Banner;
use App\Entity\LegalPage;
use App\Entity\Continent;
use App\Entity\Destination;
use App\Entity\Flight;
use App\Entity\Formule;
use App\Entity\HebergemntOffer;
use App\Entity\Highlight;
use App\Entity\Included;
use App\Entity\Informations;
use App\Entity\Itinerary;
use App\Entity\ItineraryPic;
use App\Entity\Offer;
use App\Entity\OfferHebergement;
use App\Entity\OfferInfo;
use App\Entity\QuoteRequest;
use App\Entity\TypeVoyage;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class DefaultController extends AbstractController
{
/**
* @Route("/", name="app")
*/
public function index()
{
$em = $this->getDoctrine()->getManager();
$offEscapade = $em->getRepository(Offer::class)->findBy(['type'=>1, 'isPublish'=>true]);
$offCircuit = $em->getRepository(Offer::class)->findBy(['type'=>2, 'isPublish'=>true]);
$ourOffer = $em->getRepository(Offer::class)->findBy(['OurOffer'=>1, 'isPublish'=>true]);
$infos = $em->getRepository(Informations::class)->findOneBy(['id'=>1]);
$continents = $em->getRepository(Continent::class)->findAll();
$atouts = $em->getRepository(Atouts::class)->findAll();
$banner = $em->getRepository(Banner::class)->findOneBy(['page'=>"contact"]);
//dd($atouts);
return $this->render('default/index.html.twig',[
'offEscapade'=>$offEscapade,
'offCircuit'=>$offCircuit,
'ourOffer'=>$ourOffer,
'continents'=>$continents,
'infos'=>$infos,
'atouts'=>$atouts,
'banner'=>$banner
]);
}
/**
* @Route("/search", name="search", methods={"GET"})
*/
public function search(Request $request)
{
$em = $this->getDoctrine()->getManager();
$q = trim($request->query->get('q', ''));
$results = [];
if ($q !== '') {
$results = $em->getRepository(Offer::class)->searchOffers($q);
}
//dd($results);
return $this->render('default/search.html.twig', [
'query' => $q,
'results' => $results
]);
}
/**
* @Route("/oo", name="footer")
*/
public function footer()
{
$em = $this->getDoctrine()->getManager();
$infos = $em->getRepository(Informations::class)->findOneBy(['id'=>1]);
return $this->render('default/footer.html.twig',['infos'=>$infos]);
}
/**
* @Route("/o-escapade", name="o.escapade")
*/
public function escapade()
{
$em = $this->getDoctrine()->getManager();
$offer = $em->getRepository(TypeVoyage::class)->findBy(['type'=>1]);
$offers = $em->getRepository(Offer::class)->findBy(['type'=>1, 'isPublish'=>true]);
return $this->render('default/escapade.html.twig',
['offers'=>$offers,
'offer'=>$offer,
]);
}
/**
* @Route("/continent/{slug}", name="o.continent")
*/
public function continent($slug)
{
$em = $this->getDoctrine()->getManager();
$continent = $em->getRepository(Continent::class)->findOneBy(['slug'=>$slug]);
$offers = $em->getRepository(Offer::class)->findBy(['continent'=>$continent, 'isPublish'=>true]);
return $this->render('default/continent.html.twig',
['offers'=>$offers,
'continent'=>$continent,
]);
}
/**
* @Route("/o-escapade/destination/{slug}", name="o.escapade.destination")
*/
public function escapadeDestination($slug)
{
$em = $this->getDoctrine()->getManager();
$destination = $em->getRepository(Destination::class)->findOneBy(['slug'=>$slug]);
$offer = $em->getRepository(Offer::class)->findOneBy(['destination'=>$destination->getId(), 'isPublish'=>true]);
if (!$offer) { throw $this->createNotFoundException(); }
$offerHebergement = $em->getRepository(OfferHebergement::class)->findBy(['offer'=>$offer->getId()]);
$formules = $em->getRepository(Formule::class)->findBy(['offer'=>$offer->getId()]); ;
return $this->render('default/escapade-destination.html.twig',
['destination'=>$destination,
'offerHebergement'=>$offerHebergement,
'formules'=>$formules,
'offer'=>$offer]);
}
/**
* @Route("/o-escapade", name="o.escapade")
* @Route("/o-circuit", name="o.circuit")
* @Route("/o-roadtrip", name="o.roadtrip")
* @Route("/o-croisiere", name="o.croisiere")
*/
public function Ooffers(Request $request)
{
$em = $this->getDoctrine()->getManager();
$routeName = $request->attributes->get('_route');
if($routeName == 'o.escapade'){
$typeOffer = $em->getRepository(TypeVoyage::class)->findOneBy(['id'=>1]);
$offers = $em->getRepository(Offer::class)->findBy(['type'=>1, 'isPublish'=>true]);
}
if($routeName == 'o.circuit'){
$typeOffer = $em->getRepository(TypeVoyage::class)->findOneBy(['id'=>2]);
$offers = $em->getRepository(Offer::class)->findBy(['type'=>2, 'isPublish'=>true]);
}
if($routeName == 'o.roadtrip'){
$typeOffer = $em->getRepository(TypeVoyage::class)->findOneBy(['id'=>3]);
$offers = $em->getRepository(Offer::class)->findBy(['type'=>3, 'isPublish'=>true]);
}
if($routeName == 'o.croisiere'){
$typeOffer = $em->getRepository(TypeVoyage::class)->findOneBy(['id'=>4]);
$offers = $em->getRepository(Offer::class)->findBy(['type'=>4, 'isPublish'=>true]);
}
return $this->render('default/offers.html.twig', ['offers'=>$offers,'typeOffer'=> $typeOffer]);
}
/**
* @Route("/o-circuit/destination-ex", name="o.circuit.destination-ex")
*/
public function circuitDestinationEx()
{
$em = $this->getDoctrine()->getManager();
return $this->render('default/circuit-destination-ex.html.twig');
}
/**
* @Route("/o-road/destination-ex", name="o.road.destination-ex")
*/
public function roadtDestinationEx()
{
$em = $this->getDoctrine()->getManager();
return $this->render('default/roadtrip-destination.html.twig');
}
/**
* @Route("/o-tropik-agence-de-voyage-en-guadeloupe", name="o.agency")
*/
public function agency()
{
$em = $this->getDoctrine()->getManager();
$offers = $em->getRepository(Offer::class)->findBy(['OurOffer'=>1, 'isPublish'=>true]);
return $this->render('default/agency.html.twig',['offers'=>$offers]);
}
/**
* @Route("/o-croisiere/destination-ex", name="o.ccroisiere.destination")
*/
public function oCroisiere()
{
$em = $this->getDoctrine()->getManager();
$id =3;
$offer = $em->getRepository(Offer::class)->findOneBy(['id'=>$id]);
return $this->render('default/croisiere-destination.html.twig',
['offer'=>$offer]);
}
/**
* @Route("/o-circuit/{slug}", name="o.circuit.destination")
* @Route("/o-roadtrip/{slug}", name="o.roadtrip.destination")
* @Route("/o-croisiere/{slug}", name="o.croisiere.destination")
*/
public function oOffer(Request $request, $slug)
{
$em = $this->getDoctrine()->getManager();
$routeName = $request->attributes->get('_route');
$offer = $em->getRepository(Offer::class)->findOneBy(['slug'=>$slug, 'isPublish'=>true]);
if (!$offer) { throw $this->createNotFoundException(); }
$highlight = $em->getRepository(Highlight::class)->findBy(['offer'=>$offer]);
$itinerary = $em->getRepository(Itinerary::class)->findBy(['offer'=>$offer]);
$photoItinerary = $em->getRepository(ItineraryPic::class)->findBy(['Offer'=>$offer]);
$hebergementOffer = $em->getRepository(HebergemntOffer::class)->findBy(['offer'=>$offer]);
$flight = $em->getRepository(Flight::class)->findBy(['offer'=>$offer]) ;
$infos = $em->getRepository(OfferInfo::class)->findBy(['offer'=>$offer]) ;
$included = $em->getRepository(Included::class)->findBy(['Offer'=>$offer]) ;
$routeName = $request->attributes->get('_route');
if($routeName == 'o.circuit.destination'){
return $this->render('default/circuit-destination.html.twig',
['offer'=>$offer,
'highlight'=>$highlight,
'photoItinerary'=>$photoItinerary,
'hebergementOffer'=>$hebergementOffer,
'included'=>$included,
'flight'=>$flight,
'infos'=>$infos,
'itinerary'=>$itinerary]);
}
if($routeName == 'o.roadtrip.destination'){
return $this->render('default/roadtrip-destination.html.twig',
['offer'=>$offer,
'highlight'=>$highlight,
'flight'=>$flight,
'photoItinerary'=>$photoItinerary,
'hebergementOffer'=>$hebergementOffer,
'included'=>$included,
'infos'=>$infos,
'itinerary'=>$itinerary]);
}
if($routeName == 'o.croisiere.destination'){
return $this->render('default/croisiere-destination.html.twig',
['offer'=>$offer,
'highlight'=>$highlight,
'flight'=>$flight,
'photoItinerary'=>$photoItinerary,
'hebergementOffer'=>$hebergementOffer,
'included'=>$included,
'infos'=>$infos,
'itinerary'=>$itinerary]);
}
}
/**
* @Route("/o-contact", name="o.contact")
* @Route("/demande-de-devis", name="o.devis")
*/
public function contact(Request $request)
{
$em = $this->getDoctrine()->getManager();
$routeName = $request->attributes->get('_route');
if($routeName == 'o.contact'){
$em = $this->getDoctrine()->getManager();
$infos = $em->getRepository(Informations::class)->findOneBy(['id'=>1]);
$banner = $em->getRepository(Banner::class)->findOneBy(['page'=>"contact"]);
return $this->render('default/contact.html.twig',['infos'=>$infos, 'banner'=>$banner, 'hcaptchaSiteKey'=>$_ENV['HCAPTCHA_SITE_KEY']]);
}
$routeName = $request->attributes->get('_route');
if($routeName == 'o.devis'){
$typeSejour = $em->getRepository(TypeVoyage::class)->findAll();
$banner = $em->getRepository(Banner::class)->findOneBy(['page'=>"devis"]);
return $this->render('default/devis.html.twig',['typeSejour'=>$typeSejour,'banner'=>$banner, 'hcaptchaSiteKey'=>$_ENV['HCAPTCHA_SITE_KEY']]);
}
}
/**
* @Route("/o-contact/send", name="contact.send", methods={"POST"})
*/
public function contactSend(Request $request, MailerInterface $mailer, HttpClientInterface $httpClient): Response
{
$em = $this->getDoctrine()->getManager();
$infos = $em->getRepository(Informations::class)->findOneBy(['id' => 1]);
$banner = $em->getRepository(Banner::class)->findOneBy(['page' => 'contact']);
if (!$this->verifyHCaptcha($request->request->get('h-captcha-response', ''), $httpClient)) {
$this->addFlash('error', 'Vérification anti-spam échouée. Merci de réessayer.');
return $this->render('default/contact.html.twig', ['infos' => $infos, 'banner' => $banner, 'hcaptchaSiteKey' => $_ENV['HCAPTCHA_SITE_KEY']]);
}
$name = trim((string) $request->request->get('name', ''));
$email = trim((string) $request->request->get('email', ''));
$phone = trim((string) $request->request->get('phone', ''));
$subject = trim((string) $request->request->get('subject', 'Message de contact'));
$message = trim((string) $request->request->get('message', ''));
if ($name === '' || $email === '' || $message === '') {
$this->addFlash('error', 'Merci de remplir les champs obligatoires.');
return $this->render('default/contact.html.twig', ['infos' => $infos, 'banner' => $banner]);
}
$mail = (new TemplatedEmail())
->from(new Address($_ENV['MAIL_FROM'], 'Otropik'))
->to($_ENV['MAIL_TO'])
->replyTo(new Address($email, $name))
->subject('[Contact] ' . $subject)
->htmlTemplate('emails/contact.html.twig')
->context(compact('name', 'email', 'phone', 'subject', 'message'));
$mailer->send($mail);
$this->addFlash('success', 'Votre message a bien été envoyé. Nous vous répondrons sous 24–48h.');
return $this->redirectToRoute('o.contact');
}
private function verifyHCaptcha(string $token, HttpClientInterface $httpClient): bool
{
if ($token === '') return false;
$response = $httpClient->request('POST', 'https://hcaptcha.com/siteverify', [
'body' => [
'secret' => $_ENV['HCAPTCHA_SECRET_KEY'],
'response' => $token,
],
]);
$data = $response->toArray(false);
return $data['success'] ?? false;
}
/**
* @Route("/devis/send", name="quote.request.send", methods={"POST"})
*/
public function send(Request $request, MailerInterface $mailer, HttpClientInterface $httpClient)
{
$em = $this->getDoctrine()->getManager();
if (!$this->verifyHCaptcha($request->request->get('h-captcha-response', ''), $httpClient)) {
$this->addFlash('error', 'Vérification anti-spam échouée. Merci de réessayer.');
return $this->redirectToRoute('o.devis');
}
$tripTypeId = $request->request->getInt('tripType') ?: null;
$typeSejour = $em->getRepository(TypeVoyage::class)->findOneBy(['id' => $tripTypeId]);
$destination = trim((string) $request->request->get('destination', ''));
$fullName = trim((string) $request->request->get('fullName', ''));
$clientEmail = trim((string) $request->request->get('email', ''));
if ($destination === '' || $fullName === '' || $clientEmail === '') {
$this->addFlash('error', 'Merci de remplir les champs obligatoires.');
return $this->redirectToRoute('o.devis');
}
$startDateStr = (string) $request->request->get('startDate', '');
$startDate = null;
if ($startDateStr !== '') {
try { $startDate = new \DateTimeImmutable($startDateStr); } catch (\Throwable $e) {}
}
$qr = new QuoteRequest();
$qr->setTripVoyage($typeSejour)
->setDestination($destination)
->setStartDate($startDate)
->setDurrationDays($request->request->getInt('durationDays') ?: null)
->setTravAdults(max(1, $request->request->getInt('travAdults', 2)))
->setTravChildren(max(0, $request->request->getInt('travChildren', 0)))
->setChildrenAge(trim((string) $request->request->get('childrenAges')))
->setBudgetForm($request->request->getInt('budgetFrom') ?: null)
->setBoardType(trim((string) $request->request->get('boardType')))
->setInterest(trim((string) $request->request->get('interests')))
->setMessage(trim((string) $request->request->get('message')))
->setFullName($fullName)
->setEmail($clientEmail)
->setPhone(trim((string) $request->request->get('phone')))
->setNewsletter((bool) $request->request->get('newsletter'))
->setRgpd(true)
->setCreatedAt(new \DateTimeImmutable())
->setStatus('new');
$em->persist($qr);
$em->flush();
$mail = (new TemplatedEmail())
->from(new Address($_ENV['MAIL_FROM'], 'OTropik'))
->to($_ENV['MAIL_TO'])
->replyTo(new Address($clientEmail, $fullName))
->subject('Nouvelle demande de devis — ' . $destination)
->htmlTemplate('emails/quote_request.html.twig')
->context(['qr' => $qr]);
$mailer->send($mail);
$this->addFlash('success', 'Demande envoyée ! On revient vers vous sous 24–48h ouvrées.');
return $this->redirectToRoute('o.devis');
}
/**
* @Route("/mentions-legales", name="legal.mentions")
* @Route("/conditions-generales-utilisation", name="legal.cgu")
* @Route("/politique-de-confidentialite", name="legal.privacy")
*/
public function legalPage(Request $request): Response
{
$em = $this->getDoctrine()->getManager();
$routeName = $request->attributes->get('_route');
$typeMap = [
'legal.mentions' => LegalPage::TYPE_MENTIONS,
'legal.cgu' => LegalPage::TYPE_CGU,
'legal.privacy' => LegalPage::TYPE_PRIVACY,
];
$page = $em->getRepository(LegalPage::class)->findOneBy(['type' => $typeMap[$routeName]]);
if (!$page) {
throw $this->createNotFoundException('Page légale introuvable.');
}
return $this->render('default/legal.html.twig', ['page' => $page]);
}
}