diff --git a/assets/vue/components/layout/TopbarNotLoggedIn.vue b/assets/vue/components/layout/TopbarNotLoggedIn.vue index aca33f2d2f..0a37234b0f 100644 --- a/assets/vue/components/layout/TopbarNotLoggedIn.vue +++ b/assets/vue/components/layout/TopbarNotLoggedIn.vue @@ -54,6 +54,10 @@ const menuItems = ref([ label: t("Demo"), to: { name: "Demo" }, }, + { + label: t("Contact"), + url: "/contact", + }, { key: "language_selector", label: currentLanguage ? currentLanguage.originalName : "English", diff --git a/src/CoreBundle/Controller/Admin/IndexBlocksController.php b/src/CoreBundle/Controller/Admin/IndexBlocksController.php index 2835fc55bb..d05738a14c 100644 --- a/src/CoreBundle/Controller/Admin/IndexBlocksController.php +++ b/src/CoreBundle/Controller/Admin/IndexBlocksController.php @@ -446,6 +446,12 @@ class IndexBlocksController extends BaseController 'label' => $this->translator->trans('External tools'), ]; + $items[] = [ + 'class' => 'item-contact-category-admin', + 'url' => $this->generateUrl('chamilo_contact_category_index'), + 'label' => $this->translator->trans('Contact categories'), + ]; + return $items; } diff --git a/src/CoreBundle/Controller/ContactCategoryController.php b/src/CoreBundle/Controller/ContactCategoryController.php new file mode 100644 index 0000000000..250c32303c --- /dev/null +++ b/src/CoreBundle/Controller/ContactCategoryController.php @@ -0,0 +1,89 @@ +denyAccessUnlessGranted('ROLE_ADMIN'); + + $contactCategories = $entityManager + ->getRepository(ContactCategory::class) + ->findAll(); + + return $this->render('@ChamiloCore/ContactCategory/index.html.twig', [ + 'contact_categories' => $contactCategories, + ]); + } + + #[Route('/new', name: 'chamilo_contact_category_new', methods: ['GET', 'POST'])] + public function new(Request $request, EntityManagerInterface $entityManager): Response + { + $contactCategory = new ContactCategory(); + $form = $this->createForm(ContactCategoryType::class, $contactCategory); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $entityManager->persist($contactCategory); + $entityManager->flush(); + + return $this->redirectToRoute('chamilo_contact_category_index', [], Response::HTTP_SEE_OTHER); + } + + return $this->renderForm('@ChamiloCore/ContactCategory/new.html.twig', [ + 'contact_category' => $contactCategory, + 'form' => $form, + ]); + } + + #[Route('/{id}', name: 'chamilo_contact_category_show', methods: ['GET'])] + public function show(ContactCategory $contactCategory): Response + { + return $this->render('@ChamiloCore/ContactCategory/show.html.twig', [ + 'contact_category' => $contactCategory, + ]); + } + + #[Route('/{id}/edit', name: 'chamilo_contact_category_edit', methods: ['GET', 'POST'])] + public function edit(Request $request, ContactCategory $contactCategory, EntityManagerInterface $entityManager): Response + { + $form = $this->createForm(ContactCategoryType::class, $contactCategory); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $entityManager->flush(); + + return $this->redirectToRoute('chamilo_contact_category_index', [], Response::HTTP_SEE_OTHER); + } + + return $this->renderForm('@ChamiloCore/ContactCategory/edit.html.twig', [ + 'contact_category' => $contactCategory, + 'form' => $form, + ]); + } + + #[Route('/{id}', name: 'chamilo_contact_category_delete', methods: ['POST'])] + public function delete(Request $request, ContactCategory $contactCategory, EntityManagerInterface $entityManager): Response + { + if ($this->isCsrfTokenValid('delete'.$contactCategory->getId(), $request->request->get('_token'))) { + $entityManager->remove($contactCategory); + $entityManager->flush(); + } + + return $this->redirectToRoute('chamilo_contact_category_index', [], Response::HTTP_SEE_OTHER); + } +} diff --git a/src/CoreBundle/Controller/ContactController.php b/src/CoreBundle/Controller/ContactController.php new file mode 100644 index 0000000000..92595d5ad9 --- /dev/null +++ b/src/CoreBundle/Controller/ContactController.php @@ -0,0 +1,61 @@ +createForm(ContactType::class); + $form->handleRequest($request); + + // Check if the form is submitted and valid + if ($form->isSubmitted() && $form->isValid()) { + // Get the data from the form + $contactData = $form->getData(); + $category = $contactData['category']; + $toEmail = $category->getEmail(); + + // Create and send the email + $email = (new Email()) + ->from($contactData['email']) + ->to($toEmail) + ->subject($contactData['subject']) + ->text( + "Sender: {$contactData['email']}\n". + "Message: {$contactData['message']}" + ); + + // Send the email + $mailer->send($email); + + // Add a flash message for user feedback + $this->addFlash('success', 'Your message has been sent successfully!'); + + // Redirect the user to the 'contact' route + return $this->redirectToRoute('contact'); + } + + // Render the form view + return $this->render( + '@ChamiloCore/Contact/index.html.twig', + [ + 'form' => $form->createView(), + ] + ); + } +} diff --git a/src/CoreBundle/Entity/ContactCategory.php b/src/CoreBundle/Entity/ContactCategory.php new file mode 100644 index 0000000000..c27b88aa0f --- /dev/null +++ b/src/CoreBundle/Entity/ContactCategory.php @@ -0,0 +1,55 @@ +id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): self + { + $this->name = $name; + return $this; + } + + public function getEmail(): string + { + return $this->email; + } + + public function setEmail(string $email): self + { + $this->email = $email; + return $this; + } +} diff --git a/src/CoreBundle/Form/ContactCategoryType.php b/src/CoreBundle/Form/ContactCategoryType.php new file mode 100644 index 0000000000..7b9b960cfa --- /dev/null +++ b/src/CoreBundle/Form/ContactCategoryType.php @@ -0,0 +1,26 @@ +add('name') + ->add('email') + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => ContactCategory::class, + ]); + } +} diff --git a/src/CoreBundle/Form/ContactType.php b/src/CoreBundle/Form/ContactType.php new file mode 100644 index 0000000000..9c7e458d7e --- /dev/null +++ b/src/CoreBundle/Form/ContactType.php @@ -0,0 +1,109 @@ +translator = $translator; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('category', EntityType::class, [ + 'class' => ContactCategory::class, + 'choice_label' => 'name', + 'label' => $this->translator->trans('Category'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('firstName', TextType::class, [ + 'label' => $this->translator->trans('First name'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('lastName', TextType::class, [ + 'label' => $this->translator->trans('Last name'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('email', EmailType::class, [ + 'label' => $this->translator->trans('E-mail'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('subject', TextType::class, [ + 'label' => $this->translator->trans('Subject'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('message', TextareaType::class, [ + 'label' => $this->translator->trans('Message'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('termsAccepted', CheckboxType::class, [ + 'mapped' => false, + 'label' => $this->translator->trans('By checking this box, I confirm that I accept the data processing by OFAJ'), + 'constraints' => [ + new NotBlank(), + ], + ]) + ->add('terms', TextareaType::class, [ + 'mapped' => false, + 'label' => '', + 'data' => $options['terms_content'], + 'attr' => [ + 'disabled' => true, + 'class' => 'text-gray-500', + 'style' => 'width: 100%;height: 180px;', + ], + ]) + ->add('submit', SubmitType::class, [ + 'label' => $this->translator->trans('Send'), + 'attr' => [ + 'class' => 'btn btn--primary hover:bg-blue-700 text-white font-bold py-2 px-4 rounded cursor-pointer', + 'style' => 'border: none;', + ], + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + // You can define options here if needed + $resolver->setDefaults([ + 'terms_content' => $this->translator->trans('OFAJ, responsable du traitement, met en œuvre un traitement de données à caractère personnel pour répondre à votre demande de création d’un compte utilisateur pour accéder à la plateforme de formation'), + ]); + } + + public function getName(): string + { + return 'contact'; + } +} diff --git a/src/CoreBundle/Resources/views/Contact/index.html.twig b/src/CoreBundle/Resources/views/Contact/index.html.twig new file mode 100644 index 0000000000..44304d779e --- /dev/null +++ b/src/CoreBundle/Resources/views/Contact/index.html.twig @@ -0,0 +1,56 @@ +{# templates/contact/index.html.twig #} + +{% extends "@ChamiloCore/Layout/layout_one_col.html.twig" %} + +{% block content %} +
+
+

Contact Us

+ + {{ form_start(form, {'attr': {'class': 'bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4'}}) }} + + {% for message in app.flashes('success') %} + + {% endfor %} + +
+ {{ form_label(form.category) }} + {{ form_widget(form.category, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} +
+ +
+ {{ form_label(form.firstName) }} + {{ form_widget(form.firstName, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} +
+ +
+ {{ form_label(form.lastName) }} + {{ form_widget(form.lastName, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} +
+ +
+ {{ form_label(form.email) }} + {{ form_widget(form.email, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} +
+ +
+ {{ form_label(form.subject) }} + {{ form_widget(form.subject, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} +
+ +
+ {{ form_label(form.message) }} + {{ form_widget(form.message, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} +
+ +
+ {{ form_widget(form.termsAccepted, {'attr': {'class': 'mr-2 leading-tight'}}) }} + {{ form_label(form.termsAccepted, 'By checking this box, I confirm that I accept the data processing by OFAJ') }} +
+ + {{ form_end(form) }} +
+
+{% endblock %} diff --git a/src/CoreBundle/Resources/views/ContactCategory/_delete_form.html.twig b/src/CoreBundle/Resources/views/ContactCategory/_delete_form.html.twig new file mode 100644 index 0000000000..5f3913a364 --- /dev/null +++ b/src/CoreBundle/Resources/views/ContactCategory/_delete_form.html.twig @@ -0,0 +1,7 @@ +
+ + +
diff --git a/src/CoreBundle/Resources/views/ContactCategory/_form.html.twig b/src/CoreBundle/Resources/views/ContactCategory/_form.html.twig new file mode 100644 index 0000000000..4d9bbb414d --- /dev/null +++ b/src/CoreBundle/Resources/views/ContactCategory/_form.html.twig @@ -0,0 +1,20 @@ +{{ form_start(form, {'attr': {'class': 'space-y-4'}}) }} +
+ {{ form_label(form.name, null, {'label_attr': {'class': 'block text-gray-700 text-sm font-bold mb-2'}}) }} + {{ form_widget(form.name, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} + {{ form_errors(form.name, {'attr': {'class': 'text-red-500 text-xs italic'}}) }} +
+ +
+ {{ form_label(form.email, null, {'label_attr': {'class': 'block text-gray-700 text-sm font-bold mb-2'}}) }} + {{ form_widget(form.email, {'attr': {'class': 'shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline'}}) }} + {{ form_errors(form.email, {'attr': {'class': 'text-red-500 text-xs italic'}}) }} +
+ + + + +{{ form_end(form) }} diff --git a/src/CoreBundle/Resources/views/ContactCategory/edit.html.twig b/src/CoreBundle/Resources/views/ContactCategory/edit.html.twig new file mode 100644 index 0000000000..a3e37d3f3a --- /dev/null +++ b/src/CoreBundle/Resources/views/ContactCategory/edit.html.twig @@ -0,0 +1,16 @@ +{% extends "@ChamiloCore/Layout/layout_one_col.html.twig" %} + +{% block content %} +

{{ "Edit contact category"|trans }}

+ +
+ + + {{ "Back to list"|trans }} + + + {{ include('@ChamiloCore/ContactCategory/_delete_form.html.twig') }} +
+ + {{ include('@ChamiloCore/ContactCategory/_form.html.twig', {'button_label': 'Update'}) }} +{% endblock %} diff --git a/src/CoreBundle/Resources/views/ContactCategory/index.html.twig b/src/CoreBundle/Resources/views/ContactCategory/index.html.twig new file mode 100644 index 0000000000..fefb316615 --- /dev/null +++ b/src/CoreBundle/Resources/views/ContactCategory/index.html.twig @@ -0,0 +1,41 @@ +{% extends "@ChamiloCore/Layout/layout_one_col.html.twig" %} +{% block content %} +

{{ "Contact categories"|trans }}

+ +
+ + {{ "Create new"|trans }} + + + {{ "Back to Admin"|trans }} + +
+ + + + + + + + + + + {% for contact_category in contact_categories %} + + + + + + {% else %} + + + + {% endfor %} + +
{{ "Name"|trans }}{{ "Email"|trans }}{{ "Actions"|trans }}
{{ contact_category.name }}{{ contact_category.email }} + + {{ "Edit"|trans }} + + {{ include('@ChamiloCore/ContactCategory/_delete_form.html.twig') }} +
{{ "No records found"|trans }}
+{% endblock %} diff --git a/src/CoreBundle/Resources/views/ContactCategory/new.html.twig b/src/CoreBundle/Resources/views/ContactCategory/new.html.twig new file mode 100644 index 0000000000..00105a600f --- /dev/null +++ b/src/CoreBundle/Resources/views/ContactCategory/new.html.twig @@ -0,0 +1,13 @@ +{% extends "@ChamiloCore/Layout/layout_one_col.html.twig" %} + +{% block content %} +

{{ "Create new category"|trans }}

+ +
+ + {{ "Back to list"|trans }} + +
+ + {{ include('@ChamiloCore/ContactCategory/_form.html.twig') }} +{% endblock %} diff --git a/src/CoreBundle/Resources/views/ContactCategory/show.html.twig b/src/CoreBundle/Resources/views/ContactCategory/show.html.twig new file mode 100644 index 0000000000..d7c565710b --- /dev/null +++ b/src/CoreBundle/Resources/views/ContactCategory/show.html.twig @@ -0,0 +1,28 @@ +{% extends "@ChamiloCore/Layout/layout_one_col.html.twig" %} + +{% block content %} +

{{ "Contact category"|trans }}

+ + + + + + + + + + + + + + + + +
Id{{ contact_category.id }}
Name{{ contact_category.name }}
Email{{ contact_category.email }}
+ + {{ "Back to list"|trans }} + + {{ "edit"|trans }} + + {{ include('@ChamiloCore/ContactCategory/_delete_form.html.twig') }} +{% endblock %}