Polish footer UI and localize demo-request form endpoints

This commit is contained in:
2026-03-23 00:28:52 +01:00
parent d2adda383e
commit ca06ab88ba
5 changed files with 460 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
{% load wagtailimages_tags %}
<section class="saas-demo saas-demo--inline saas-demo--{{ self.background_style }}"
data-width="{{ self.layout_width }}">
<div class="saas-demo__container">
<header class="saas-demo__header">
<h2 class="saas-demo__title">{{ self.section_title }}</h2>
{% if self.section_subtitle %}
<div class="saas-demo__subtitle">{{ self.section_subtitle }}</div>
{% endif %}
</header>
<form class="saas-demo__form" action="{% url "contact_form:contact-form-handler" %}" method="post">
{% csrf_token %}
<div class="saas-demo__fields">
{% for field in self.form_fields %}
<div class="saas-demo__field">
<label class="saas-demo__label" for="demo-{{ field.field_type }}">
{{ field.label }}
{% if field.required %}<span class="saas-demo__required">*</span>{% endif %}
</label>
{% if field.field_type == 'message' %}
<textarea class="saas-demo__textarea"
id="demo-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
placeholder="{{ field.placeholder }}"
{% if field.required %}required{% endif %}></textarea>
{% elif field.field_type == 'company_size' %}
<select class="saas-demo__select"
id="demo-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
{% if field.required %}required{% endif %}>
<option value="">{{ field.placeholder|default:"Select company size" }}</option>
<option value="1-10">1-10 employees</option>
<option value="11-50">11-50 employees</option>
<option value="51-200">51-200 employees</option>
<option value="201-500">201-500 employees</option>
<option value="500+">500+ employees</option>
</select>
{% else %}
<input class="saas-demo__input"
type="{% if field.field_type == 'email' %}email{% elif field.field_type == 'phone' %}tel{% else %}text{% endif %}"
id="demo-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
placeholder="{{ field.placeholder }}"
{% if field.required %}required{% endif %}>
{% endif %}
</div>
{% endfor %}
</div>
<button type="submit" class="saas-demo__submit">{{ self.submit_button_text }}</button>
{% if self.privacy_text %}
<div class="saas-demo__privacy">{{ self.privacy_text }}</div>
{% endif %}
</form>
</div>
</section>

View File

@@ -0,0 +1,94 @@
{% load wagtailimages_tags %}
<section class="saas-demo saas-demo--modal-trigger saas-demo--{{ self.background_style }}"
data-width="{{ self.layout_width }}"
data-demo-modal-root>
<div class="saas-demo__container">
<div class="saas-demo__content">
<h2 class="saas-demo__title">{{ self.section_title }}</h2>
{% if self.section_subtitle %}
<div class="saas-demo__subtitle">{{ self.section_subtitle }}</div>
{% endif %}
<button type="button" class="saas-demo__trigger" data-demo-modal-open>
{{ self.submit_button_text }}
</button>
</div>
</div>
<!-- Modal -->
<div class="saas-demo__modal" data-demo-modal hidden>
<div class="saas-demo__modal-backdrop" data-demo-modal-close></div>
<div class="saas-demo__modal-content">
<button type="button" class="saas-demo__modal-close" data-demo-modal-close aria-label="Close">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</button>
<h3 class="saas-demo__modal-title">{{ self.section_title }}</h3>
<form class="saas-demo__form" action="{% url "contact_form:contact-form-handler" %}" method="post">
{% csrf_token %}
<div class="saas-demo__fields">
{% for field in self.form_fields %}
<div class="saas-demo__field">
<label class="saas-demo__label" for="modal-{{ field.field_type }}">
{{ field.label }}
{% if field.required %}<span class="saas-demo__required">*</span>{% endif %}
</label>
{% if field.field_type == 'message' %}
<textarea class="saas-demo__textarea"
id="modal-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
placeholder="{{ field.placeholder }}"
{% if field.required %}required{% endif %}></textarea>
{% else %}
<input class="saas-demo__input"
type="{% if field.field_type == 'email' %}email{% elif field.field_type == 'phone' %}tel{% else %}text{% endif %}"
id="modal-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
placeholder="{{ field.placeholder }}"
{% if field.required %}required{% endif %}>
{% endif %}
</div>
{% endfor %}
</div>
<button type="submit" class="saas-demo__submit">{{ self.submit_button_text }}</button>
{% if self.privacy_text %}
<div class="saas-demo__privacy">{{ self.privacy_text }}</div>
{% endif %}
</form>
</div>
</div>
</section>
<script>
(function () {
const roots = document.querySelectorAll('[data-demo-modal-root]');
roots.forEach((root) => {
if (root.dataset.modalBound === "1") return;
root.dataset.modalBound = "1";
const modal = root.querySelector('[data-demo-modal]');
const openBtn = root.querySelector('[data-demo-modal-open]');
const closeBtns = root.querySelectorAll('[data-demo-modal-close]');
if (!modal || !openBtn) return;
const openModal = () => {
modal.hidden = false;
document.body.style.overflow = 'hidden';
};
const closeModal = () => {
modal.hidden = true;
document.body.style.overflow = '';
};
openBtn.addEventListener('click', openModal);
closeBtns.forEach((btn) => btn.addEventListener('click', closeModal));
root.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && !modal.hidden) closeModal();
});
});
})();
</script>

View File

@@ -0,0 +1,156 @@
{% load wagtailimages_tags %}
<section class="saas-demo saas-demo--split saas-demo--{{ self.background_style }} mandelstudio-demo-split"
data-width="{{ self.layout_width }}">
<style>
.mandelstudio-demo-split {
position: relative;
border-radius: 18px;
overflow: hidden;
background: linear-gradient(180deg, #f8fbff 0%, #f3f7fc 100%);
}
.mandelstudio-demo-split .saas-demo__container {
max-width: 1200px;
margin: 0 auto;
padding: clamp(1.25rem, 2.2vw, 2.25rem);
gap: clamp(1rem, 2vw, 2rem);
}
.mandelstudio-demo-split .saas-demo__title {
font-size: clamp(1.9rem, 3vw, 3rem);
line-height: 1.1;
letter-spacing: -0.03em;
margin-bottom: .8rem;
}
.mandelstudio-demo-split .saas-demo__subtitle {
color: #556070;
max-width: 54ch;
margin-bottom: .9rem;
}
.mandelstudio-demo-split .saas-demo__benefits-list {
margin-bottom: 1.15rem;
}
.mandelstudio-demo-split .saas-demo__benefit {
color: #212b3a;
}
.mandelstudio-demo-split .saas-demo__visual {
margin-top: .5rem;
}
.mandelstudio-demo-split .saas-demo__image {
width: 100%;
border-radius: 16px;
border: 1px solid rgba(39, 66, 107, .14);
box-shadow: 0 12px 28px rgba(20, 35, 68, .12);
}
.mandelstudio-demo-split .saas-demo__form-wrapper {
border: 1px solid rgba(42, 72, 120, .15);
border-radius: 16px;
background: #fff;
box-shadow: 0 14px 30px rgba(18, 38, 76, .09);
}
.mandelstudio-demo-split .saas-demo__form {
padding: clamp(1rem, 2vw, 1.5rem);
}
.mandelstudio-demo-split .saas-demo__input,
.mandelstudio-demo-split .saas-demo__select,
.mandelstudio-demo-split .saas-demo__textarea {
background: #fbfdff;
border-color: #d8e1ec;
transition: border-color .2s ease, box-shadow .2s ease;
}
.mandelstudio-demo-split .saas-demo__input:focus,
.mandelstudio-demo-split .saas-demo__select:focus,
.mandelstudio-demo-split .saas-demo__textarea:focus {
border-color: #377dff;
box-shadow: 0 0 0 .2rem rgba(55, 125, 255, .15);
}
.mandelstudio-demo-split .saas-demo__submit {
box-shadow: 0 8px 18px rgba(40, 95, 214, .3);
}
@media (max-width: 991.98px) {
.mandelstudio-demo-split .saas-demo__visual {
display: none;
}
}
</style>
<div class="saas-demo__container">
<div class="saas-demo__content">
<h2 class="saas-demo__title">{{ self.section_title }}</h2>
{% if self.section_subtitle %}
<div class="saas-demo__subtitle">{{ self.section_subtitle }}</div>
{% endif %}
{% if self.benefits_title or self.benefits %}
<div class="saas-demo__benefits">
{% if self.benefits_title %}
<h3 class="saas-demo__benefits-title">{{ self.benefits_title }}</h3>
{% endif %}
{% if self.benefits %}
<ul class="saas-demo__benefits-list">
{% for benefit in self.benefits %}
<li class="saas-demo__benefit">
<svg class="saas-demo__check" width="20" height="20" viewBox="0 0 20 20" fill="none">
<path d="M4 10L8 14L16 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
{{ benefit }}
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
{% if self.side_image %}
<div class="saas-demo__visual">
{% image self.side_image width-640 class="saas-demo__image" %}
</div>
{% endif %}
</div>
<div class="saas-demo__form-wrapper">
<form class="saas-demo__form" action="{% url "contact_form:contact-form-handler" %}" method="post">
{% csrf_token %}
<div class="saas-demo__fields">
{% for field in self.form_fields %}
<div class="saas-demo__field">
<label class="saas-demo__label" for="split-{{ field.field_type }}">
{{ field.label }}
{% if field.required %}<span class="saas-demo__required">*</span>{% endif %}
</label>
{% if field.field_type == 'message' %}
<textarea class="saas-demo__textarea"
id="split-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
placeholder="{{ field.placeholder }}"
{% if field.required %}required{% endif %}></textarea>
{% elif field.field_type == 'company_size' %}
<select class="saas-demo__select"
id="split-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
{% if field.required %}required{% endif %}>
<option value="">{{ field.placeholder|default:"Select company size" }}</option>
<option value="1-10">1-10 employees</option>
<option value="11-50">11-50 employees</option>
<option value="51-200">51-200 employees</option>
<option value="201-500">201-500 employees</option>
<option value="500+">500+ employees</option>
</select>
{% else %}
<input class="saas-demo__input"
type="{% if field.field_type == 'email' %}email{% elif field.field_type == 'phone' %}tel{% else %}text{% endif %}"
id="split-{{ field.field_type }}"
name="{% if field.field_type == "email" %}email_from{% elif field.field_type == "phone" %}phonenumber{% elif field.field_type == "text" %}name{% else %}{{ field.field_type }}{% endif %}"
placeholder="{{ field.placeholder }}"
{% if field.required %}required{% endif %}>
{% endif %}
</div>
{% endfor %}
</div>
<button type="submit" class="saas-demo__submit">{{ self.submit_button_text }}</button>
{% if self.privacy_text %}
<div class="saas-demo__privacy">{{ self.privacy_text }}</div>
{% endif %}
</form>
</div>
</div>
</section>

View File

@@ -0,0 +1,11 @@
{% load wagtailcore_tags %}
{% if self.heading %}<p class="footer_header">{{ self.heading }}</p>{% endif %}
{% if children %}
<ul class="mb-footer-links list-unstyled m-0">
{% for page in children %}
<li class="mb-footer-links__item mb-2">
<a href="{% pageurl page %}">{{ page.title }}</a>
</li>
{% endfor %}
</ul>
{% endif %}

View File

@@ -0,0 +1,141 @@
{% load staticfiles %}
{% load wagtailcore_tags wagtailimages_tags wagtailsettings_tags cache %}
{% get_settings %}
{% cache 300 footer_menu LANGUAGE_CODE request.site %}
<style>
.mb-footer-wrap {
margin-top: clamp(2rem, 4vw, 3.5rem);
position: relative;
}
.mb-footer {
position: relative;
background:
radial-gradient(120% 120% at 0% 0%, rgba(84, 149, 230, .22) 0%, rgba(84, 149, 230, 0) 45%),
radial-gradient(90% 120% at 100% 0%, rgba(65, 206, 186, .16) 0%, rgba(65, 206, 186, 0) 45%),
linear-gradient(180deg, #264f72 0%, #203f5c 100%);
border-radius: 28px 28px 0 0;
padding: clamp(2rem, 4vw, 3rem) 0;
box-shadow:
inset 0 1px 0 rgba(255,255,255,.12),
0 -10px 24px rgba(20, 43, 72, .20);
overflow: hidden;
}
.mb-footer:before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(90deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 35%, rgba(255,255,255,.06) 100%);
pointer-events: none;
}
.mb-footer .footer_column {
padding-top: .75rem;
padding-bottom: .75rem;
}
.mb-footer .mb-footer__card {
height: 100%;
background: rgba(255, 255, 255, .055);
border: 1px solid rgba(255, 255, 255, .14);
border-radius: 16px;
padding: 1.1rem 1.15rem;
backdrop-filter: blur(1.2px);
}
.mb-footer .footer_header {
font-size: 1.05rem;
font-weight: 700;
letter-spacing: .01em;
margin-bottom: .9rem;
color: #f4f8ff;
}
.mb-footer .footer_column,
.mb-footer .footer_column * {
color: rgba(237, 244, 255, .93);
}
.mb-footer .footer_column a {
color: #eef4ff;
text-decoration: none;
transition: color .2s ease, transform .2s ease;
}
.mb-footer .footer_column a:hover {
color: #ffffff;
transform: translateX(2px);
}
.mb-footer .footer_column .rich-text p {
margin-bottom: .65rem;
line-height: 1.65;
max-width: 34ch;
}
.mb-footer .mb-footer__card .aboutus-logo {
max-height: 52px;
width: auto;
}
.mb-footer .mb-footer__card .social {
margin-top: 1rem;
}
.mb-footer .mb-footer__card .social a {
border-color: rgba(255, 255, 255, .42);
color: #ffffff;
background: rgba(255,255,255,.08);
}
.mb-footer .mb-footer__card .social a:hover {
background: rgba(255,255,255,.18);
}
.mb-copyright {
background: #1b3650;
padding: 1rem 0;
border-top: 1px solid rgba(255,255,255,.16);
}
.mb-copyright .copyright_block,
.mb-copyright .copyright_block * {
color: rgba(234, 241, 255, .92);
margin: 0;
font-size: .95rem;
}
.mb-copyright .copyright_block a {
color: #ffffff;
text-decoration: none;
}
.mb-copyright .copyright_block a:hover {
text-decoration: underline;
}
@media (max-width: 991.98px) {
.mb-footer {
border-radius: 20px 20px 0 0;
}
.mb-footer .mb-footer__card {
padding: 1rem;
}
}
</style>
<div class="mb-footer-wrap">
<footer class="footer mb-footer">
<div class="container">
<div class="row g-4">
{% with footer=settings.ocyan_plugin_wagtail.OcyanSettings.footer %}
{% for block in footer %}
{% if block.block_type == 'page_list' and block.value.page and not block.value.page.get_children.live.public %}
{% else %}
<div class="{% if footer|length == 3 %}col-lg-4{% elif footer|length == 2 %}col-lg-6{% else %}col-lg-3{% endif %} col-md-6 col-sm-12 footer_column {{ block.block_type|slugify }}">
<div class="mb-footer__card">
{% include_block block %}
</div>
</div>
{% endif %}
{% endfor %}
{% endwith %}
</div>
</div>
</footer>
<section class="copyright_wrapper mb-copyright">
<div class="container">
<div class="row">
<div class="col-lg-12 copyright_block">
{% include_block settings.ocyan_plugin_wagtail.OcyanSettings.mini_footer %}
</div>
</div>
</div>
</section>
</div>
{% endcache %}