Add contact page
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@plugin "@tailwindcss/forms";
|
|
||||||
@source not "../../public";
|
|
||||||
@theme {
|
@theme {
|
||||||
--font-sans: InterVariable, sans-serif;
|
--font-sans: InterVariable, sans-serif;
|
||||||
--font-sans--font-feature-settings: "cv02", "cv03", "cv04", "cv11";
|
--font-sans--font-feature-settings: "cv02", "cv03", "cv04", "cv11";
|
||||||
}
|
}
|
||||||
@import "./css/swiper.css";
|
@import "./css/swiper.css";
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
twig:
|
twig:
|
||||||
file_name_pattern: "*.twig"
|
file_name_pattern: "*.twig"
|
||||||
form_themes:
|
|
||||||
- "form/custom_tailwind_theme.html.twig"
|
|
||||||
|
|
||||||
when@test:
|
when@test:
|
||||||
twig:
|
twig:
|
||||||
strict_variables: true
|
strict_variables: true
|
||||||
|
|||||||
31
migrations/Version20260117031003.php
Normal file
31
migrations/Version20260117031003.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20260117031003 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE TABLE configuration (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, owner_mail VARCHAR(255) DEFAULT NULL, PRIMARY KEY (id))');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('DROP TABLE configuration');
|
||||||
|
}
|
||||||
|
}
|
||||||
31
migrations/Version20260117033945.php
Normal file
31
migrations/Version20260117033945.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20260117033945 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE TABLE contact (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, send_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, is_valid BOOLEAN NOT NULL, PRIMARY KEY (id))');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('DROP TABLE contact');
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/Controller/ConfigurationController.php
Normal file
43
src/Controller/ConfigurationController.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Configuration;
|
||||||
|
use App\Form\ConfigurationType;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
|
final class ConfigurationController extends AbstractController
|
||||||
|
{
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
public function __construct(EntityManagerInterface $entityManager)
|
||||||
|
{
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/admin/configuration', name: 'admin_configuration_index')]
|
||||||
|
public function index(Request $request): Response
|
||||||
|
{
|
||||||
|
$configuration = $this->entityManager->getRepository(Configuration::class)->findOneBy(['id' => 1]);
|
||||||
|
$form = $this->createForm(ConfigurationType::class, $configuration);
|
||||||
|
$form->handleRequest($request);
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$isConfiguration = $this->entityManager->getRepository(Configuration::class)->findOneBy(['id' => 1]);
|
||||||
|
if ($isConfiguration) {
|
||||||
|
$isConfiguration->setOwnerMail($form->getData()->getOwnerMail());
|
||||||
|
} else {
|
||||||
|
$configuration = new Configuration();
|
||||||
|
$configuration->setOwnerMail($form->getData()->getOwnerMail());
|
||||||
|
$this->entityManager->persist($configuration);
|
||||||
|
}
|
||||||
|
$this->entityManager->flush();
|
||||||
|
}
|
||||||
|
return $this->render('configuration/index.html.twig', [
|
||||||
|
'form' => $form->createView(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,18 +3,26 @@
|
|||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\News;
|
use App\Entity\News;
|
||||||
|
use App\Entity\Contact;
|
||||||
|
use App\Form\ContactType;
|
||||||
|
use App\Service\MailService;
|
||||||
|
use DateTimeImmutable;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Exception;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
final class PageController extends AbstractController
|
final class PageController extends AbstractController
|
||||||
{
|
{
|
||||||
private EntityManagerInterface $entityManager;
|
private EntityManagerInterface $entityManager;
|
||||||
|
private MailService $mailService;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $entityManager)
|
public function __construct(EntityManagerInterface $entityManager, MailService $mailService)
|
||||||
{
|
{
|
||||||
$this->entityManager = $entityManager;
|
$this->entityManager = $entityManager;
|
||||||
|
$this->mailService = $mailService;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/', name: 'home')]
|
#[Route('/', name: 'home')]
|
||||||
@@ -47,6 +55,43 @@ final class PageController extends AbstractController
|
|||||||
return $this->render('page/show.html.twig', []);
|
return $this->render('page/show.html.twig', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/contact', name: 'contact')]
|
||||||
|
public function contact(Request $request): Response
|
||||||
|
{
|
||||||
|
$form = $this->createForm(ContactType::class);
|
||||||
|
$form->handleRequest($request);
|
||||||
|
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$contact = new Contact();
|
||||||
|
$contact->setSendAt(new DateTimeImmutable());
|
||||||
|
$data = $form->getData();
|
||||||
|
|
||||||
|
$honeyPot = $form->getData()['mobilePhoneNumber'];
|
||||||
|
if ($honeyPot !== NULL) {
|
||||||
|
$contact->setIsValid(false);
|
||||||
|
$this->addFlash('success', 'Votre message a été envoyé avec succès.');
|
||||||
|
$this->entityManager->persist($contact);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
return $this->redirectToRoute('contact');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$this->mailService->sendContactMail($data);
|
||||||
|
$contact->setIsValid(true);
|
||||||
|
$this->addFlash('success', 'Votre message a été envoyé avec succès.');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$contact->setIsValid(false);
|
||||||
|
$this->addFlash('error', 'Une erreur est survenue lors de l’envoi du message.');
|
||||||
|
}
|
||||||
|
$this->entityManager->persist($contact);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
return $this->redirectToRoute('contact');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('page/contact.html.twig', [
|
||||||
|
'form' => $form->createView(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
#[Route('/mentions-legales', name: 'legalmentions')]
|
#[Route('/mentions-legales', name: 'legalmentions')]
|
||||||
public function legalmentions(): Response
|
public function legalmentions(): Response
|
||||||
{
|
{
|
||||||
|
|||||||
35
src/Entity/Configuration.php
Normal file
35
src/Entity/Configuration.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Repository\ConfigurationRepository;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
#[ORM\Entity(repositoryClass: ConfigurationRepository::class)]
|
||||||
|
class Configuration
|
||||||
|
{
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue]
|
||||||
|
#[ORM\Column]
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[ORM\Column(length: 255, nullable: true)]
|
||||||
|
private ?string $ownerMail = null;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOwnerMail(): ?string
|
||||||
|
{
|
||||||
|
return $this->ownerMail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOwnerMail(?string $ownerMail): static
|
||||||
|
{
|
||||||
|
$this->ownerMail = $ownerMail;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/Entity/Contact.php
Normal file
50
src/Entity/Contact.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Repository\ContactRepository;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
#[ORM\Entity(repositoryClass: ContactRepository::class)]
|
||||||
|
class Contact
|
||||||
|
{
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue]
|
||||||
|
#[ORM\Column]
|
||||||
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[ORM\Column]
|
||||||
|
private ?\DateTimeImmutable $sendAt = null;
|
||||||
|
|
||||||
|
#[ORM\Column]
|
||||||
|
private ?bool $isValid = null;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSendAt(): ?\DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->sendAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSendAt(\DateTimeImmutable $sendAt): static
|
||||||
|
{
|
||||||
|
$this->sendAt = $sendAt;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(): ?bool
|
||||||
|
{
|
||||||
|
return $this->isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setIsValid(bool $isValid): static
|
||||||
|
{
|
||||||
|
$this->isValid = $isValid;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/Form/ConfigurationType.php
Normal file
44
src/Form/ConfigurationType.php
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form;
|
||||||
|
|
||||||
|
use App\Entity\Configuration;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class ConfigurationType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('ownerMail', EmailType::class, [
|
||||||
|
'label' => 'Email du propriétaire',
|
||||||
|
'label_attr' => [
|
||||||
|
'class' => 'block text-sm font-semibold text-gray-900',
|
||||||
|
],
|
||||||
|
'attr' => [
|
||||||
|
'class' => 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 border border-gray-300 placeholder:text-gray-400 focus:border-amber-600 focus:ring-2 focus:ring-amber-600/30 focus:outline-none',
|
||||||
|
],
|
||||||
|
'row_attr' => [
|
||||||
|
'class' => 'space-y-1',
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->add('submit', SubmitType::class, [
|
||||||
|
'label' => 'Enregistrer',
|
||||||
|
'attr' => [
|
||||||
|
'class' => 'mt-2 inline-flex items-center justify-center rounded-md bg-amber-600 px-3.5 py-2.5 text-base font-semibold text-white shadow-sm hover:bg-amber-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-600',
|
||||||
|
],
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => Configuration::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/Form/ContactType.php
Normal file
47
src/Form/ContactType.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
|
class ContactType extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('lastName', TextType::class, [
|
||||||
|
'constraints' => [new Assert\NotBlank()],
|
||||||
|
])
|
||||||
|
->add('firstName', TextType::class, [
|
||||||
|
'constraints' => [new Assert\NotBlank()],
|
||||||
|
])
|
||||||
|
->add('company', TextType::class, [
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('email', EmailType::class, [
|
||||||
|
'constraints' => [
|
||||||
|
new Assert\NotBlank(),
|
||||||
|
new Assert\Email(),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->add('phoneNumber', TextType::class, [
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('mobilePhoneNumber', TextType::class, [
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('message', TextareaType::class, [
|
||||||
|
'constraints' => [new Assert\NotBlank()],
|
||||||
|
])
|
||||||
|
->add('agreeToPolicies', CheckboxType::class, [
|
||||||
|
'constraints' => [new Assert\IsTrue()],
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,15 @@ class NewsType extends AbstractType
|
|||||||
$builder
|
$builder
|
||||||
->add('title', TextType::class, [
|
->add('title', TextType::class, [
|
||||||
'label' => 'Titre',
|
'label' => 'Titre',
|
||||||
|
'label_attr' => [
|
||||||
|
'class' => 'block text-sm font-semibold text-gray-900',
|
||||||
|
],
|
||||||
|
'attr' => [
|
||||||
|
'class' => 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 border border-gray-300 placeholder:text-gray-400 focus:border-amber-600 focus:ring-2 focus:ring-amber-600/30 focus:outline-none',
|
||||||
|
],
|
||||||
|
'row_attr' => [
|
||||||
|
'class' => 'space-y-1',
|
||||||
|
],
|
||||||
])
|
])
|
||||||
->add('description', CKEditor5Type::class, [
|
->add('description', CKEditor5Type::class, [
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
|||||||
43
src/Repository/ConfigurationRepository.php
Normal file
43
src/Repository/ConfigurationRepository.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\Configuration;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ServiceEntityRepository<Configuration>
|
||||||
|
*/
|
||||||
|
class ConfigurationRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, Configuration::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return Configuration[] Returns an array of Configuration objects
|
||||||
|
// */
|
||||||
|
// public function findByExampleField($value): array
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('c')
|
||||||
|
// ->andWhere('c.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->orderBy('c.id', 'ASC')
|
||||||
|
// ->setMaxResults(10)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public function findOneBySomeField($value): ?Configuration
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('c')
|
||||||
|
// ->andWhere('c.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getOneOrNullResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
}
|
||||||
43
src/Repository/ContactRepository.php
Normal file
43
src/Repository/ContactRepository.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\Contact;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ServiceEntityRepository<Contact>
|
||||||
|
*/
|
||||||
|
class ContactRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, Contact::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return Contact[] Returns an array of Contact objects
|
||||||
|
// */
|
||||||
|
// public function findByExampleField($value): array
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('c')
|
||||||
|
// ->andWhere('c.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->orderBy('c.id', 'ASC')
|
||||||
|
// ->setMaxResults(10)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public function findOneBySomeField($value): ?Contact
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('c')
|
||||||
|
// ->andWhere('c.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getOneOrNullResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
}
|
||||||
36
src/Service/MailService.php
Normal file
36
src/Service/MailService.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
use App\Entity\Configuration;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||||
|
use Symfony\Component\Mailer\MailerInterface;
|
||||||
|
use Symfony\Component\Mime\Email;
|
||||||
|
|
||||||
|
class MailService
|
||||||
|
{
|
||||||
|
private MailerInterface $mailer;
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
public function __construct(MailerInterface $mailer, EntityManagerInterface $entityManager)
|
||||||
|
{
|
||||||
|
$this->mailer = $mailer;
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendContactMail(array $data): void
|
||||||
|
{
|
||||||
|
$configuration = $this->entityManager->getRepository(Configuration::class)->findOneBy(['id' => 1]);
|
||||||
|
$email = (new TemplatedEmail())
|
||||||
|
->from($configuration->getOwnerMail())
|
||||||
|
->to($configuration->getOwnerMail())
|
||||||
|
->replyTo($data["email"])
|
||||||
|
->subject('Nouvelle demande de contact')
|
||||||
|
->htmlTemplate('mail/contact.html.twig')
|
||||||
|
->context([
|
||||||
|
'data' => $data,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->mailer->send($email);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -315,6 +315,19 @@
|
|||||||
<span class="truncate">Fonctionnalité</span>
|
<span class="truncate">Fonctionnalité</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="{{ path('admin_configuration_index') }}"
|
||||||
|
class="group flex gap-x-3 rounded-md p-2 text-sm/6 font-semibold hover:bg-gray-50 hover:text-amber-600{% if path starts with '/admin/configuration' %} bg-gray-50 text-amber-600 {% else %} text-gray-700 hover:bg-gray-50 hover:text-amber-600{% endif %}"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="flex size-6 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-white text-[0.625rem] font-medium {% if path starts with '/admin/configuration' %} border-amber-600 text-amber-600 {% else %} text-gray-400 group-hover:border-amber-600 group-hover:text-amber-600{% endif %}"
|
||||||
|
>
|
||||||
|
C
|
||||||
|
</span>
|
||||||
|
<span class="truncate">Configuration</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -64,8 +64,8 @@
|
|||||||
Me connaître
|
Me connaître
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="tel:+33672701956"
|
href="{{ path('contact') }}"
|
||||||
class="text-sm/6 font-semibold text-gray-900 bg-amber-300 rounded-2xl px-4 py-2 hover:bg-amber-400 transition-colors"
|
class="text-sm/6 font-semibold text-gray-900"
|
||||||
>
|
>
|
||||||
Me contacter
|
Me contacter
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
27
templates/configuration/index.html.twig
Normal file
27
templates/configuration/index.html.twig
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{% extends 'base_admin.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Configuration
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<main class="lg:pl-72">
|
||||||
|
<div class="xl:pr-96">
|
||||||
|
<div class="px-4 py-10 sm:px-6 lg:px-8 lg:py-6">
|
||||||
|
{{ form_start(form) }}
|
||||||
|
{{ form_widget(form) }}
|
||||||
|
{{ form_end(form) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<aside
|
||||||
|
class="fixed inset-y-0 right-0 hidden w-96 overflow-y-auto border-l border-gray-200 px-4 py-6 sm:px-6 lg:px-8 xl:block dark:border-white/10"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="rounded-md bg-amber-600 px-4 py-2.5 text-sm font-semibold text-white shadow-xs hover:bg-amber-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-600 dark:bg-amber-500 dark:shadow-none dark:hover:bg-amber-400 dark:focus-visible:outline-amber-500"
|
||||||
|
>
|
||||||
|
Modifier la configuration
|
||||||
|
</a>
|
||||||
|
</aside>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{% use 'tailwind_2_layout.html.twig' %}
|
|
||||||
|
|
||||||
{%- block form_row -%}
|
|
||||||
{%- set row_class = row_class|default('mb-4 flex flex-col space-y-1') -%}
|
|
||||||
{{- parent() -}}{%- endblock form_row -%}{%- block widget_attributes -%}{%- set widget_class = widget_class|default('block w-full rounded-lg border-gray-300 focus:border-amber-500 focus:ring-amber-500') -%}{%- set widget_disabled_class = widget_disabled_class|default('opacity-50 cursor-not-allowed') -%}{%- set widget_errors_class = widget_errors_class|default('border-red-500 ring-red-500') -%}{{- parent() -}}{%- endblock widget_attributes -%}{%- block form_label -%}{%- set label_class = label_class|default('font-medium text-gray-700') -%}{{- parent() -}}{%- endblock form_label -%}{%- block form_help -%}{%- set help_class = help_class|default('text-sm text-gray-500') -%}{{- parent() -}}{%- endblock form_help -%}{%- block form_errors -%}{%- set error_item_class = error_item_class|default('text-sm text-red-600') -%}{{- parent() -}}{%- endblock form_errors -%}
|
|
||||||
238
templates/mail/contact.html.twig
Normal file
238
templates/mail/contact.html.twig
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>
|
||||||
|
Nouveau message de contact
|
||||||
|
</title>
|
||||||
|
<style media="all" type="text/css">
|
||||||
|
/* ------------------------------------- GLOBAL RESETS
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
body { font-family: Helvetica, sans-serif; -webkit-font-smoothing:
|
||||||
|
antialiased; font-size: 16px; line-height: 1.3; -ms-text-size-adjust:
|
||||||
|
100%; -webkit-text-size-adjust: 100%; }
|
||||||
|
|
||||||
|
table { border-collapse: separate; mso-table-lspace: 0pt;
|
||||||
|
mso-table-rspace: 0pt; width: 100%; }
|
||||||
|
|
||||||
|
table td { font-family: Helvetica, sans-serif; font-size: 16px;
|
||||||
|
vertical-align: top; } /* ------------------------------------- BODY &
|
||||||
|
CONTAINER ------------------------------------- */
|
||||||
|
|
||||||
|
body { background-color: #f4f5f6; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
.body { background-color: #f4f5f6; width: 100%; }
|
||||||
|
|
||||||
|
.container { margin: 0 auto !important; max-width: 600px; padding: 0;
|
||||||
|
padding-top: 24px; width: 600px; }
|
||||||
|
|
||||||
|
.content { box-sizing: border-box; display: block; margin: 0 auto;
|
||||||
|
max-width: 600px; padding: 0; } /* -------------------------------------
|
||||||
|
HEADER, FOOTER, MAIN ------------------------------------- */
|
||||||
|
|
||||||
|
.main { background: #ffffff; border: 1px solid #eaebed; border-radius:
|
||||||
|
16px; width: 100%; }
|
||||||
|
|
||||||
|
.wrapper { box-sizing: border-box; padding: 24px; }
|
||||||
|
|
||||||
|
.footer { clear: both; padding-top: 24px; text-align: center; width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer td, .footer p, .footer span, .footer a { color: #9a9ea6;
|
||||||
|
font-size: 16px; text-align: center; } /*
|
||||||
|
------------------------------------- TYPOGRAPHY
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
p { font-family: Helvetica, sans-serif; font-size: 16px; font-weight:
|
||||||
|
normal; margin: 0; margin-bottom: 16px; }
|
||||||
|
|
||||||
|
a { color: #0867ec; text-decoration: underline; } /*
|
||||||
|
------------------------------------- BUTTONS
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
.btn { box-sizing: border-box; min-width: 100% !important; width: 100%; }
|
||||||
|
|
||||||
|
.btn > tbody > tr > td { padding-bottom: 16px; }
|
||||||
|
|
||||||
|
.btn table { width: auto; }
|
||||||
|
|
||||||
|
.btn table td { background-color: #ffffff; border-radius: 4px; text-align:
|
||||||
|
center; }
|
||||||
|
|
||||||
|
.btn a { background-color: #ffffff; border: solid 2px #0867ec;
|
||||||
|
border-radius: 4px; box-sizing: border-box; color: #0867ec; cursor:
|
||||||
|
pointer; display: inline-block; font-size: 16px; font-weight: bold;
|
||||||
|
margin: 0; padding: 12px 24px; text-decoration: none; text-transform:
|
||||||
|
capitalize; }
|
||||||
|
|
||||||
|
.btn-primary table td { background-color: #0867ec; }
|
||||||
|
|
||||||
|
.btn-primary a { background-color: #0867ec; border-color: #0867ec; color:
|
||||||
|
#ffffff; }
|
||||||
|
|
||||||
|
@media all { .btn-primary table td:hover { background-color: #ec0867
|
||||||
|
!important; } .btn-primary a:hover { background-color: #ec0867 !important;
|
||||||
|
border-color: #ec0867 !important; } }
|
||||||
|
|
||||||
|
/* ------------------------------------- OTHER STYLES THAT MIGHT BE USEFUL
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
.last { margin-bottom: 0; }
|
||||||
|
|
||||||
|
.first { margin-top: 0; }
|
||||||
|
|
||||||
|
.align-center { text-align: center; }
|
||||||
|
|
||||||
|
.align-right { text-align: right; }
|
||||||
|
|
||||||
|
.align-left { text-align: left; }
|
||||||
|
|
||||||
|
.text-link { color: #0867ec !important; text-decoration: underline
|
||||||
|
!important; }
|
||||||
|
|
||||||
|
.clear { clear: both; }
|
||||||
|
|
||||||
|
.mt0 { margin-top: 0; }
|
||||||
|
|
||||||
|
.mb0 { margin-bottom: 0; }
|
||||||
|
|
||||||
|
.preheader { color: transparent; display: none; height: 0; max-height: 0;
|
||||||
|
max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility:
|
||||||
|
hidden; width: 0; }
|
||||||
|
|
||||||
|
.powered-by a { text-decoration: none; }
|
||||||
|
|
||||||
|
/* ------------------------------------- RESPONSIVE AND MOBILE FRIENDLY
|
||||||
|
STYLES ------------------------------------- */
|
||||||
|
|
||||||
|
@media only screen and (max-width: 640px) { .main p, .main td, .main span
|
||||||
|
{ font-size: 16px !important; } .wrapper { padding: 8px !important; }
|
||||||
|
.content { padding: 0 !important; } .container { padding: 0 !important;
|
||||||
|
padding-top: 8px !important; width: 100% !important; } .main {
|
||||||
|
border-left-width: 0 !important; border-radius: 0 !important;
|
||||||
|
border-right-width: 0 !important; } .btn table { max-width: 100%
|
||||||
|
!important; width: 100% !important; } .btn a { font-size: 16px !important;
|
||||||
|
max-width: 100% !important; width: 100% !important; } } /*
|
||||||
|
------------------------------------- PRESERVE THESE STYLES IN THE HEAD
|
||||||
|
------------------------------------- */
|
||||||
|
|
||||||
|
@media all { .ExternalClass { width: 100%; } .ExternalClass,
|
||||||
|
.ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass
|
||||||
|
td, .ExternalClass div { line-height: 100%; } .apple-link a { color:
|
||||||
|
inherit !important; font-family: inherit !important; font-size: inherit
|
||||||
|
!important; font-weight: inherit !important; line-height: inherit
|
||||||
|
!important; text-decoration: none !important; } #MessageViewBody a {
|
||||||
|
color: inherit; text-decoration: none; font-size: inherit; font-family:
|
||||||
|
inherit; font-weight: inherit; line-height: inherit; } }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table
|
||||||
|
role="presentation"
|
||||||
|
border="0"
|
||||||
|
cellpadding="0"
|
||||||
|
cellspacing="0"
|
||||||
|
class="body"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td> </td>
|
||||||
|
<td class="container">
|
||||||
|
<div class="content">
|
||||||
|
<!-- START CENTERED WHITE CONTAINER -->
|
||||||
|
<span class="preheader">Nouveau message de contact</span>
|
||||||
|
<table
|
||||||
|
role="presentation"
|
||||||
|
border="0"
|
||||||
|
cellpadding="0"
|
||||||
|
cellspacing="0"
|
||||||
|
class="main"
|
||||||
|
>
|
||||||
|
<!-- START MAIN CONTENT AREA -->
|
||||||
|
<tr>
|
||||||
|
<td class="wrapper">
|
||||||
|
<p>
|
||||||
|
{{ data.lastName }} {{ data.firstName }}
|
||||||
|
</p>
|
||||||
|
{% if data.company %}
|
||||||
|
<p>
|
||||||
|
{{ data.company }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<p>
|
||||||
|
{{ data.message }}
|
||||||
|
</p>
|
||||||
|
<table
|
||||||
|
role="presentation"
|
||||||
|
border="0"
|
||||||
|
cellpadding="0"
|
||||||
|
cellspacing="0"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="left">
|
||||||
|
<table
|
||||||
|
role="presentation"
|
||||||
|
border="0"
|
||||||
|
cellpadding="0"
|
||||||
|
cellspacing="0"
|
||||||
|
>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a
|
||||||
|
href="https://arts-ticule.fr"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Voir le site
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p>
|
||||||
|
Mon adresse électronique : {{ data.email }}
|
||||||
|
</p>
|
||||||
|
{% if data.phoneNumber %}
|
||||||
|
<p>
|
||||||
|
Mes coordonnées téléphoniques : {{ data.phoneNumber }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- END MAIN CONTENT AREA -->
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- START FOOTER -->
|
||||||
|
<div class="footer">
|
||||||
|
<table
|
||||||
|
role="presentation"
|
||||||
|
border="0"
|
||||||
|
cellpadding="0"
|
||||||
|
cellspacing="0"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td class="content-block">
|
||||||
|
<span class="apple-link">Arts-Ticule</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- END FOOTER -->
|
||||||
|
|
||||||
|
<!-- END CENTERED WHITE CONTAINER -->
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
311
templates/page/contact.html.twig
Normal file
311
templates/page/contact.html.twig
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
{% block metadata %}
|
||||||
|
{# ============================
|
||||||
|
METADATA / SEO
|
||||||
|
============================ #}
|
||||||
|
|
||||||
|
{% set meta_title = meta_title is defined
|
||||||
|
? meta_title
|
||||||
|
: 'Contact – Spectacles vivants et artisanat pour collectivités'
|
||||||
|
%}
|
||||||
|
{% set meta_description = meta_description is defined
|
||||||
|
? meta_description
|
||||||
|
: 'Contactez-nous pour vos projets de spectacles vivants et de créations artisanales destinés aux collectivités, écoles et lieux culturels.'
|
||||||
|
%}
|
||||||
|
{% set meta_image = meta_image is defined
|
||||||
|
? meta_image
|
||||||
|
: asset('images/logo.jpg')
|
||||||
|
%}
|
||||||
|
{% set meta_url = meta_url is defined ? meta_url : app.request.uri %}
|
||||||
|
{% set meta_site_name = meta_site_name is defined
|
||||||
|
? meta_site_name
|
||||||
|
: 'Nom du site'
|
||||||
|
%}
|
||||||
|
{% set meta_type = meta_type is defined ? meta_type : 'website' %}
|
||||||
|
|
||||||
|
<title>
|
||||||
|
{{ meta_title }}
|
||||||
|
</title>
|
||||||
|
|
||||||
|
<meta name="description" content="{{ meta_description }}" />
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
|
<link rel="canonical" href="{{ meta_url }}" />
|
||||||
|
|
||||||
|
{# ============================
|
||||||
|
OPEN GRAPH (Facebook, LinkedIn…)
|
||||||
|
============================ #}
|
||||||
|
|
||||||
|
<meta property="og:title" content="{{ meta_title }}" />
|
||||||
|
<meta property="og:description" content="{{ meta_description }}" />
|
||||||
|
<meta property="og:type" content="{{ meta_type }}" />
|
||||||
|
<meta property="og:url" content="{{ meta_url }}" />
|
||||||
|
<meta property="og:image" content="{{ meta_image }}" />
|
||||||
|
<meta property="og:site_name" content="{{ meta_site_name }}" />
|
||||||
|
<meta property="og:locale" content="fr_FR" />
|
||||||
|
|
||||||
|
{# Optionnel mais recommandé #}
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
|
||||||
|
{# ============================
|
||||||
|
TWITTER CARDS
|
||||||
|
============================ #}
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="{{ meta_title }}" />
|
||||||
|
<meta name="twitter:description" content="{{ meta_description }}" />
|
||||||
|
<meta name="twitter:image" content="{{ meta_image }}" />
|
||||||
|
{% endblock %}
|
||||||
|
{% block body %}
|
||||||
|
<div class="isolate bg-white px-6 py-24 sm:py-32 lg:px-8">
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
class="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="clip-path: polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)"
|
||||||
|
class="relative left-1/2 -z-10 aspect-1155/678 w-144.5 max-w-none -translate-x-1/2 rotate-30 bg-linear-to-tr from-[#ff80b5] to-[#F59E0B] opacity-30 sm:left-[calc(50%-40rem)] sm:w-288.75"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div class="mx-auto max-w-2xl text-center">
|
||||||
|
<h2
|
||||||
|
class="text-4xl font-semibold tracking-tight text-balance text-gray-900 sm:text-5xl"
|
||||||
|
>
|
||||||
|
Contactez moi
|
||||||
|
</h2>
|
||||||
|
<p class="mt-2 text-lg/8 text-gray-600">
|
||||||
|
Vous pouvez me contacter via le formulaire ci-dessous et je vous
|
||||||
|
répondrai rapidement.
|
||||||
|
</p>
|
||||||
|
{% for label, messages in app.flashes %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<div
|
||||||
|
class="mb-6 rounded-md p-4 text-sm font-medium {% if label == 'success' %} bg-green-50 text-green-800 {% elseif label == 'error' %} bg-red-50 text-red-800 {% elseif label == 'warning' %} bg-yellow-50 text-yellow-800 {% endif %}"
|
||||||
|
>
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{
|
||||||
|
form_start(
|
||||||
|
form,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
class: 'mx-auto mt-16 max-w-xl sm:mt-20'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<div class="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="{{ form.lastName.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Nom
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.lastName,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
placeholder: 'Votre nom',
|
||||||
|
autocomplete: 'family-name',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label
|
||||||
|
for="{{ form.firstName.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Prénom
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.firstName,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
placeholder: 'Votre prénom',
|
||||||
|
autocomplete: 'given-name',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<label
|
||||||
|
for="{{ form.company.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Entreprise
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.company,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
placeholder: 'Raison sociale',
|
||||||
|
autocomplete: 'organization',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<label
|
||||||
|
for="{{ form.email.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Email
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.email,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
placeholder: 'Votre adresse email',
|
||||||
|
autocomplete: 'email',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<label
|
||||||
|
for="{{ form.phoneNumber.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Numéro de téléphone
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.phoneNumber,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
placeholder: 'Votre numéro de téléphone',
|
||||||
|
autocomplete: 'tel',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-2 hidden">
|
||||||
|
<label
|
||||||
|
for="{{ form.phoneNumber.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Numéro de téléphone mobile
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.mobilePhoneNumber,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
placeholder: 'Votre numéro de téléphone',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<label
|
||||||
|
for="{{ form.message.vars.id }}"
|
||||||
|
class="block text-sm/6 font-semibold text-gray-900"
|
||||||
|
>
|
||||||
|
Message
|
||||||
|
</label>
|
||||||
|
<div class="mt-2.5">
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.message,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
rows: 4,
|
||||||
|
placeholder: 'Votre message',
|
||||||
|
class: 'block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-amber-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex gap-x-4 sm:col-span-2">
|
||||||
|
<div class="flex h-6 items-center">
|
||||||
|
<div
|
||||||
|
class="group relative inline-flex w-8 shrink-0 rounded-full bg-gray-200 p-px inset-ring inset-ring-gray-900/5 outline-offset-2 outline-amber-600 transition-colors duration-200 ease-in-out has-checked:bg-amber-600 has-focus-visible:outline-2"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="size-4 rounded-full bg-white shadow-xs ring-1 ring-gray-900/5 transition-transform duration-200 ease-in-out group-has-checked:translate-x-3.5"
|
||||||
|
>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{{
|
||||||
|
form_widget(
|
||||||
|
form.agreeToPolicies,
|
||||||
|
{
|
||||||
|
attr: {
|
||||||
|
class: 'absolute inset-0 size-full appearance-none focus:outline-hidden'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label
|
||||||
|
for="{{ form.agreeToPolicies.vars.id }}"
|
||||||
|
class="text-sm/6 text-gray-600"
|
||||||
|
>
|
||||||
|
En cochant cette case, vous acceptez notre
|
||||||
|
<a
|
||||||
|
href="{{ path('confidentialitypolicy') }}"
|
||||||
|
class="font-semibold whitespace-nowrap text-amber-600"
|
||||||
|
>
|
||||||
|
politique de confidentialité
|
||||||
|
</a>.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-10">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="block w-full rounded-md bg-amber-600 px-3.5 py-2.5 text-center text-sm font-semibold text-white shadow-xs hover:bg-amber-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-600"
|
||||||
|
>
|
||||||
|
Envoyer ma demande
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{{ form_end(form) }}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user