Version stable, aprelic, connexion CFRS et autres corrections

This commit is contained in:
Oleg Barykin committed 2026-04-17 20:18:11 +02:00
1 parent 865de8a976
commit e9d0010451
62 files changed
+17483 -7256

No files matched your search

+538
View File
@@ -0,0 +1,538 @@
<?php
declare (strict_types = 1);
if (! function_exists('t')) {
function t(array $translations, string $key, string $fallback = ''): string
{
$val = $translations[$key] ?? '';
return $val !== '' ? (string) $val : $fallback;
}
}
$form_index_status = $form_index_status ?? null;
$form_index_message = $form_index_message ?? '';
$form_index_errors = $form_index_errors ?? [];
$form_index_old = $form_index_old ?? [
'name' => '',
'category' => '',
'situation' => '',
'contact_type' => 'email',
'email' => '',
'wa' => '',
];
?>
<section class="concierge-section" id="concierge-form">
<div class="concierge-inner">
<div class="concierge-heading">
<span class="label"><?php echo htmlspecialchars(t($translations, 'form_index_badge', 'Бесплатно · Без регистрации'), ENT_QUOTES, 'UTF-8'); ?></span>
<h2><?php echo htmlspecialchars(t($translations, 'form_index_title', 'Не можете найти нужного специалиста?'), ENT_QUOTES, 'UTF-8'); ?></h2>
<p><?php echo htmlspecialchars(t($translations, 'form_index_intro', 'Опишите вашу ситуацию — мы сами подберём подходящего русскоязычного специалиста во Франции и свяжемся с вами.'), ENT_QUOTES, 'UTF-8'); ?></p>
</div>
<div class="concierge-card">
<div class="card-stripe"></div>
<?php if ($form_index_status !== 'success'): ?>
<div class="card-form" id="formState">
<?php if ($form_index_status === 'error' && $form_index_message !== ''): ?>
<div class="form-alert form-alert-error">
<?php echo htmlspecialchars($form_index_message, ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?>
<form method="post" action="">
<input type="hidden" name="form_index" value="1">
<div style="position:absolute;left:-9999px;opacity:0;pointer-events:none;" aria-hidden="true">
<label for="form_index_company">Company</label>
<input type="text" name="company" id="form_index_company" tabindex="-1" autocomplete="off">
</div>
<div class="fields-grid">
<div class="field">
<label for="f-name">
<?php echo htmlspecialchars(t($translations, 'form_index_name_label', 'Ваше имя'), ENT_QUOTES, 'UTF-8'); ?>
<span class="req">*</span>
</label>
<input
type="text"
id="f-name"
name="name"
placeholder="<?php echo htmlspecialchars(t($translations, 'form_index_name_placeholder', 'Как вас зовут?'), ENT_QUOTES, 'UTF-8'); ?>"
autocomplete="given-name"
value="<?php echo htmlspecialchars($form_index_old['name'], ENT_QUOTES, 'UTF-8'); ?>"
class="<?php echo ! empty($form_index_errors['name']) ? 'error' : ''; ?>"
>
</div>
<div class="field">
<label for="f-category">
<?php echo htmlspecialchars(t($translations, 'form_index_category_label', 'Нужен специалист'), ENT_QUOTES, 'UTF-8'); ?>
<span class="req">*</span>
</label>
<select id="f-category" name="category" class="<?php echo ! empty($form_index_errors['category']) ? 'error' : ''; ?>">
<option value=""><?php echo htmlspecialchars(t($translations, 'form_index_category_placeholder', 'Выберите категорию'), ENT_QUOTES, 'UTF-8'); ?></option>
<?php
$categories = [
'lawyer' => 'form_index_category_lawyer',
'notary' => 'form_index_category_notary',
'real_estate' => 'form_index_category_real_estate',
'psychologist' => 'form_index_category_psychologist',
'dentist_ortho' => 'form_index_category_dentist_ortho',
'financial_advisor' => 'form_index_category_financial_advisor',
'translator' => 'form_index_category_translator',
'residence_consultant' => 'form_index_category_residence_consultant',
'repair' => 'form_index_category_repair',
'funeral' => 'form_index_category_funeral',
'other' => 'form_index_category_other',
];
foreach ($categories as $value => $key):
?>
<option value="<?php echo htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); ?>" <?php echo $form_index_old['category'] === $value ? 'selected' : ''; ?>>
<?php echo htmlspecialchars(t($translations, $key, $value), ENT_QUOTES, 'UTF-8'); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="field field-full">
<label for="f-situation">
<?php echo htmlspecialchars(t($translations, 'form_index_situation_label', 'Опишите вашу ситуацию'), ENT_QUOTES, 'UTF-8'); ?>
<span class="req">*</span>
</label>
<textarea
id="f-situation"
name="situation"
placeholder="<?php echo htmlspecialchars(t($translations, 'form_index_situation_placeholder', 'Расскажите кратко — что случилось, что нужно сделать, в каком городе вы находитесь…'), ENT_QUOTES, 'UTF-8'); ?>"
class="<?php echo ! empty($form_index_errors['situation']) ? 'error' : ''; ?>"
><?php echo htmlspecialchars($form_index_old['situation'], ENT_QUOTES, 'UTF-8'); ?></textarea>
</div>
<div class="field field-full">
<div class="contact-label-row">
<label>
<?php echo htmlspecialchars(t($translations, 'form_index_contact_label', 'Как с вами связаться'), ENT_QUOTES, 'UTF-8'); ?>
<span class="req">*</span>
</label>
<div class="contact-tabs">
<button class="ctab <?php echo $form_index_old['contact_type'] === 'email' ? 'active' : ''; ?>" type="button" data-contact-tab="email">
<?php echo htmlspecialchars(t($translations, 'form_index_contact_tab_email', 'Email'), ENT_QUOTES, 'UTF-8'); ?>
</button>
<button class="ctab <?php echo $form_index_old['contact_type'] === 'wa' ? 'active' : ''; ?>" type="button" data-contact-tab="wa">
<?php echo htmlspecialchars(t($translations, 'form_index_contact_tab_wa', 'WhatsApp'), ENT_QUOTES, 'UTF-8'); ?>
</button>
</div>
</div>
<input type="hidden" name="contact_type" id="contact_type" value="<?php echo htmlspecialchars($form_index_old['contact_type'], ENT_QUOTES, 'UTF-8'); ?>">
<div class="contact-input <?php echo $form_index_old['contact_type'] === 'email' ? 'show' : ''; ?>" id="ci-email">
<input
type="email"
id="f-email"
name="email"
placeholder="<?php echo htmlspecialchars(t($translations, 'form_index_email_placeholder', 'votre@email.com'), ENT_QUOTES, 'UTF-8'); ?>"
autocomplete="email"
value="<?php echo htmlspecialchars($form_index_old['email'], ENT_QUOTES, 'UTF-8'); ?>"
class="<?php echo ! empty($form_index_errors['email']) ? 'error' : ''; ?>"
>
</div>
<div class="contact-input <?php echo $form_index_old['contact_type'] === 'wa' ? 'show' : ''; ?>" id="ci-wa">
<input
type="tel"
id="f-wa"
name="wa"
placeholder="<?php echo htmlspecialchars(t($translations, 'form_index_wa_placeholder', '+33 6 00 00 00 00'), ENT_QUOTES, 'UTF-8'); ?>"
autocomplete="tel"
value="<?php echo htmlspecialchars($form_index_old['wa'], ENT_QUOTES, 'UTF-8'); ?>"
class="<?php echo ! empty($form_index_errors['wa']) ? 'error' : ''; ?>"
>
</div>
</div>
</div>
<button class="btn-submit" type="submit">
<?php echo htmlspecialchars(t($translations, 'form_index_submit', 'Подобрать специалиста'), ENT_QUOTES, 'UTF-8'); ?>
</button>
<p class="form-note">
<?php echo htmlspecialchars(t($translations, 'form_index_note', 'Мы не передаём ваши данные третьим лицам и свяжемся с вами в течение нескольких часов.'), ENT_QUOTES, 'UTF-8'); ?>
</p>
</form>
</div>
<?php else: ?>
<div class="card-success" id="successState" style="display:block;">
<div class="success-circle">✓</div>
<h3><?php echo htmlspecialchars(t($translations, 'form_index_success_title', 'Заявка получена!'), ENT_QUOTES, 'UTF-8'); ?></h3>
<p><?php echo htmlspecialchars(t($translations, 'form_index_success_text', 'Мы изучим вашу ситуацию и свяжемся с вами в ближайшее время, чтобы предложить подходящего специалиста.'), ENT_QUOTES, 'UTF-8'); ?></p>
</div>
<?php endif; ?>
</div>
</div>
</section>
<style>
.concierge-section {
font-family: 'Montserrat', sans-serif;
background: #f7f8fc;
padding: 52px 20px;
width: 100%;
}
.concierge-inner { max-width: 700px; margin: 0 auto; }
.concierge-heading { text-align: center; margin-bottom: 32px; }
.concierge-heading .label {
display: inline-block;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: #2e4db0;
background: #eef2fb;
padding: 5px 14px;
border-radius: 20px;
margin-bottom: 14px;
}
.concierge-heading h2 {
font-size: clamp(20px, 4vw, 26px);
font-weight: 700;
color: #1e2d5a;
line-height: 1.3;
margin-bottom: 10px;
}
.concierge-heading p {
font-size: 14px;
font-weight: 400;
color: #6b7280;
line-height: 1.65;
max-width: 500px;
margin: 0 auto;
}
.concierge-card {
background: #fff;
border-radius: 20px;
border: 1.5px solid #dde3f0;
box-shadow: 0 4px 24px rgba(30,45,90,0.08);
overflow: hidden;
}
.card-stripe {
height: 4px;
background: linear-gradient(90deg, #1e2d5a 0%, #2e4db0 100%);
}
.card-form { padding: 32px 36px 36px; }
.fields-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
margin-bottom: 16px;
}
.field-full { grid-column: 1 / -1; }
.field { display: flex; flex-direction: column; gap: 7px; }
.field label {
font-size: 12px;
font-weight: 600;
color: #1e2d5a;
letter-spacing: 0.03em;
text-transform: uppercase;
}
.field label .req { color: #2e4db0; margin-left: 2px; }
.card-form input,
.card-form textarea,
.card-form select {
font-family: 'Montserrat', sans-serif;
font-size: 14px;
font-weight: 400;
color: #1e2d5a;
background: #f7f8fc;
border: 1.5px solid #dde3f0;
border-radius: 8px;
padding: 11px 14px;
outline: none;
transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
width: 100%;
appearance: none;
}
.card-form input::placeholder,
.card-form textarea::placeholder { color: #b0b8cc; font-weight: 300; }
.card-form input:focus,
.card-form textarea:focus,
.card-form select:focus {
border-color: #2e4db0;
background: #fff;
box-shadow: 0 0 0 3px rgba(46,77,176,0.09);
}
.card-form input.error,
.card-form textarea.error,
.card-form select.error {
border-color: #d73a3a;
background: #fff8f8;
}
.card-form textarea {
resize: vertical;
min-height: 100px;
line-height: 1.6;
}
.card-form select {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' fill='none'%3E%3Cpath d='M1 1l4.5 4.5L10 1' stroke='%231e2d5a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 14px center;
padding-right: 38px;
cursor: pointer;
}
.contact-label-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 7px;
}
.contact-tabs {
display: flex;
gap: 4px;
background: #f7f8fc;
border: 1.5px solid #dde3f0;
border-radius: 6px;
padding: 3px;
}
.ctab {
font-family: 'Montserrat', sans-serif;
font-size: 11px;
font-weight: 600;
padding: 4px 10px;
border-radius: 4px;
border: none;
background: none;
color: #6b7280;
cursor: pointer;
transition: all 0.15s;
letter-spacing: 0.02em;
}
.ctab.active {
background: #1e2d5a;
color: #fff;
}
.contact-input { display: none; }
.contact-input.show { display: flex; flex-direction: column; gap: 7px; }
.btn-submit {
width: 100%;
margin-top: 20px;
background: #e03c3f;
color: #fff;
font-family: 'Montserrat', sans-serif;
font-size: 14px;
font-weight: 700;
letter-spacing: 0.04em;
border: none;
border-radius: 999px;
padding: 14px 24px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
transition: background 0.18s, transform 0.12s, box-shadow 0.18s;
}
.btn-submit:hover {
background: #e03c3f;
box-shadow: 0 6px 20px rgba(30,45,90,0.22);
}
.btn-submit:active { transform: translateY(0); box-shadow: none; }
.btn-icon {
width: 22px;
height: 22px;
border-radius: 50%;
background: rgba(255,255,255,0.18);
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
transition: transform 0.18s;
}
.btn-submit:hover .btn-icon { transform: translateX(3px); }
.form-note {
text-align: center;
font-size: 11px;
color: #6b7280;
margin-top: 12px;
line-height: 1.5;
font-weight: 400;
}
.form-alert {
margin-bottom: 18px;
padding: 12px 14px;
border-radius: 10px;
font-size: 14px;
line-height: 1.5;
}
.form-alert-error {
background: #fff4f4;
border: 1px solid #f0caca;
color: #9f1d1d;
}
.card-success {
display: none;
padding: 52px 36px;
text-align: center;
animation: fadeIn 0.35s ease both;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
.success-circle {
width: 56px;
height: 56px;
border-radius: 50%;
background: #1e2d5a;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 18px;
font-size: 24px;
color: white;
}
.card-success h3 {
font-size: 20px;
font-weight: 700;
color: #1e2d5a;
margin-bottom: 10px;
}
.card-success p {
font-size: 14px;
color: #6b7280;
line-height: 1.65;
max-width: 380px;
margin: 0 auto;
font-weight: 400;
}
@media (max-width: 540px) {
.card-form { padding: 24px 20px 28px; }
.fields-grid { grid-template-columns: 1fr; }
.card-success { padding: 36px 20px; }
.concierge-section { padding: 36px 16px; }
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const tabs = document.querySelectorAll('[data-contact-tab]');
const typeInput = document.getElementById('contact_type');
const emailWrap = document.getElementById('ci-email');
const waWrap = document.getElementById('ci-wa');
function switchTab(type) {
typeInput.value = type;
tabs.forEach(btn => {
btn.classList.toggle('active', btn.dataset.contactTab === type);
});
emailWrap.classList.toggle('show', type === 'email');
waWrap.classList.toggle('show', type === 'wa');
}
tabs.forEach(btn => {
btn.addEventListener('click', function () {
switchTab(this.dataset.contactTab);
});
});
switchTab(typeInput.value || 'email');
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const tabs = document.querySelectorAll('[data-contact-tab]');
const typeInput = document.getElementById('contact_type');
const emailWrap = document.getElementById('ci-email');
const waWrap = document.getElementById('ci-wa');
function switchTab(type) {
typeInput.value = type;
tabs.forEach(btn => {
btn.classList.toggle('active', btn.dataset.contactTab === type);
});
emailWrap.classList.toggle('show', type === 'email');
waWrap.classList.toggle('show', type === 'wa');
}
tabs.forEach(btn => {
btn.addEventListener('click', function () {
switchTab(this.dataset.contactTab);
});
});
switchTab(typeInput.value || 'email');
});
</script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<?php if ($form_index_status === 'success' || $form_index_status === 'error'): ?>
<script>
document.addEventListener('DOMContentLoaded', function () {
Swal.fire({
icon: <?php echo json_encode($form_index_status === 'success' ? 'success' : 'error'); ?>,
title: <?php
echo json_encode(
$form_index_status === 'success'
? t($translations, 'form_index_success_title', 'Заявка получена!')
: t($translations, 'form_index_error_popup_title', 'Ошибка')
);
?>,
text: <?php echo json_encode($form_index_message); ?>,
confirmButtonText: 'OK',
confirmButtonColor: '#1e2d5a'
});
});
</script>
<?php endif; ?>