feat: add FAQ question form with email notifications and validations
All checks were successful
Build and Push Docker Image / build (push) Successful in 43s
All checks were successful
Build and Push Docker Image / build (push) Successful in 43s
- Created `FaqQuestionForm` in `forms.py` with custom field validations - Added FAQ form to the FAQ section with CSRF protection and error handling - Integrated email notifications to administrator upon FAQ submission - Updated styles and scripts for form inputs, validation messages, and messages UI - Adjusted FAQ section layout in `faq.html` and related CSS for responsiveness - Implemented tests for FAQ form submission and email notifications
This commit is contained in:
@@ -20,7 +20,36 @@
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% if messages %}
|
||||
<div class="site-toast-stack" aria-live="polite" aria-atomic="true">
|
||||
{% for message in messages %}
|
||||
<div class="site-toast site-toast--{{ message.tags }}" data-toast>
|
||||
<div class="site-toast__content">{{ message }}</div>
|
||||
<button class="site-toast__close" type="button" aria-label="Закрыть уведомление" data-toast-close>×</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('[data-toast]').forEach(function (toast) {
|
||||
const closeButton = toast.querySelector('[data-toast-close]')
|
||||
const hideToast = function () {
|
||||
toast.classList.add('is-hiding')
|
||||
window.setTimeout(function () {
|
||||
toast.remove()
|
||||
}, 220)
|
||||
}
|
||||
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener('click', hideToast)
|
||||
}
|
||||
|
||||
window.setTimeout(hideToast, 4000)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<section class="faq-section container">
|
||||
<section class="faq-section container" id="faq-section">
|
||||
<h2>ОТВЕТЫ НА ВОПРОСЫ</h2>
|
||||
<div class="faq-grid">
|
||||
|
||||
@@ -44,23 +44,30 @@
|
||||
|
||||
<div id="back-form" style="display: none;" class="back-form">
|
||||
<h2>НЕ НАШЛИ ОТВЕТ НА ВАШ ВОПРОС?</h2>
|
||||
<form action="">
|
||||
<label class="q-label" for="name" style="margin-top: 69px;">
|
||||
<input type="text" placeholder="Имя" id="name">
|
||||
</label>
|
||||
<form action="{% url 'home' %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ faq_form.non_field_errors }}
|
||||
|
||||
<label class="q-label" for="number">
|
||||
<input type="text" placeholder="Номер телефона" id="number">
|
||||
<label class="q-label" for="{{ faq_form.name.id_for_label }}" style="margin-top: 69px;">
|
||||
{{ faq_form.name }}
|
||||
</label>
|
||||
{{ faq_form.name.errors }}
|
||||
|
||||
<label class="q-label" for="question">
|
||||
<input type="text" placeholder="Ваш вопрос" id="question">
|
||||
<label class="q-label" for="{{ faq_form.phone.id_for_label }}">
|
||||
{{ faq_form.phone }}
|
||||
</label>
|
||||
{{ faq_form.phone.errors }}
|
||||
|
||||
<label class="q-label" for="{{ faq_form.question.id_for_label }}">
|
||||
{{ faq_form.question }}
|
||||
</label>
|
||||
{{ faq_form.question.errors }}
|
||||
|
||||
<div class="back-form-accept-checkbox">
|
||||
<input type="checkbox" id="accept" name="accept">
|
||||
<label for="accept">Я согласен с политикой обработки персональных данных</label>
|
||||
{{ faq_form.accept }}
|
||||
<label for="{{ faq_form.accept.id_for_label }}">{{ faq_form.accept.label }}</label>
|
||||
</div>
|
||||
{{ faq_form.accept.errors }}
|
||||
|
||||
<button class="back-form-submit" type="submit">ОТПРАВИТЬ ВОПРОС</button>
|
||||
</form>
|
||||
@@ -78,5 +85,12 @@
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
Fancybox.bind('[data-fancybox]')
|
||||
|
||||
{% if faq_form.is_bound and faq_form.errors %}
|
||||
const openFaqButton = document.querySelector('.faq-cta a[data-fancybox]')
|
||||
if (openFaqButton) {
|
||||
openFaqButton.click()
|
||||
}
|
||||
{% endif %}
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -4,13 +4,44 @@
|
||||
{% block title %}Главная{% endblock %}
|
||||
|
||||
{% block add_css %}
|
||||
|
||||
<link rel="stylesheet" href="{% static 'css/warranty.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% include "_fragments/header.html" %}
|
||||
<div class="full-page">
|
||||
<div>
|
||||
{% include "_fragments/header.html" with active="warranty" breadcrumb=1 %}
|
||||
{% include '_fragments/breadcrumbs.html' with url_1='/' text_1='Главная' url_2='/warranty' text_2='Гарантия' %}
|
||||
</div>
|
||||
|
||||
{# TODO #}
|
||||
В разработке
|
||||
{% include "_fragments/footer.html" %}
|
||||
<main class="warranty container">
|
||||
<h1>ГАРАНТИЯ НА ТОВАР</h1>
|
||||
<p>
|
||||
В каталоге нашего интернет-магазина представлены только качественные товары от лучших производителей. Мы
|
||||
закупаем только сертифицированный товар и только у официальных импортеров и производителей. Покупая
|
||||
сантехнику в нашем магазине, Вы приобретаете товары только с гарантией! Все гарантийное и
|
||||
постгарантийное обслуживание товаров производится специализированными авторизированными сервисными
|
||||
центрами фирм производителей, имеющих на то соответствующие полномочия. Данные условия гарантируют
|
||||
отсутствие в изделии дефектов и удовлетворяют законным требованиям Потребителя в течение гарантийного
|
||||
срока с момента передачи товара Потребителю.
|
||||
</p>
|
||||
<h2>Условия гарантии:</h2>
|
||||
<p>
|
||||
Гарантия не распространяется на неисправности, вызванные неправильным монтажом, чисткой абразивными или
|
||||
едкими веществами, неправильными эксплуатацией и ремонтом. Внимательно изучите прилагаемую инструкцию по
|
||||
эксплуатации.
|
||||
</p>
|
||||
<p>
|
||||
Гарантийные обязательства не распространяются на расходные элементы и материалы (батареи, картриджи,
|
||||
комплектующие и т.п.), а также на ремонт или замену естественно изнашиваемых в процессе эксплуатации
|
||||
запчастей.
|
||||
</p>
|
||||
<p>
|
||||
В гарантийном обслуживании может быть отказано, если установка и ремонт изделий производились лицами, не
|
||||
имеющими соответствующих полномочий и квалификации.
|
||||
</p>
|
||||
</main>
|
||||
|
||||
{% include "_fragments/footer.html" %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -8,7 +8,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="auth-page">
|
||||
<div class="full-page">
|
||||
{% include "_fragments/header.html" %}
|
||||
|
||||
<main class="auth-section">
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="auth-actions">
|
||||
<div class="register-auth-actions">
|
||||
<button class="auth-submit" type="submit">Создать аккаунт</button>
|
||||
<p class="auth-switch">
|
||||
Уже есть аккаунт?
|
||||
|
||||
Reference in New Issue
Block a user