Derniere version de site au 4/10/2026
This commit is contained in:
1 parent
21f34c64c9
commit
dbb8e299a0
35 files changed
+8697
-1242
No files matched your search
Generated
+6
@@ -0,0 +1,6 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="USLUGI_BD" uuid="ee47d4b7-b40e-4b04-8b18-3457e823b1de">
|
||||
<driver-ref>mariadb</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:mariadb://mariadb:3306/uslugi_db</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="DBE_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/maria_uslugi.iml" filepath="$PROJECT_DIR$/.idea/maria_uslugi.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,74 +1,98 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
declare (strict_types = 1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void {
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string {
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') return $fallback;
|
||||
return (string)$val;
|
||||
}
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (string)$lang : 'ru';
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string
|
||||
{
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return (string) $val;
|
||||
}
|
||||
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru';
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<html lang="<?php echo htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars($translations['seo_about_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_about_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_about_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_about_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_about_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_about_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<?php include_once __DIR__ . '/includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php if (is_client_logged_in()): ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php else: ?>
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
@@ -88,8 +112,8 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-none d-sm-inline"><?= htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -99,15 +123,15 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?= htmlspecialchars(t($translations, 'about_help_aria', 'Help'), ENT_QUOTES, 'UTF-8') ?>">
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'about_help_aria', 'Help'), ENT_QUOTES, 'UTF-8') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/about.php"><?= htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/faq.php"><?= htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/contact.php"><?= htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -151,67 +175,67 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
<div class="wrap">
|
||||
|
||||
<div class="card" style="margin-bottom:18px;">
|
||||
<h2><?= htmlspecialchars(t($translations, 'about_intro_title', 'About'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_intro_text', 'uslugi.fr is a platform...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'about_intro_title', 'About'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_intro_text', 'uslugi.fr is a platform...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
|
||||
<div class="about-grid">
|
||||
<div class="card">
|
||||
<h2><?= htmlspecialchars(t($translations, 'about_mission_title', 'Our mission'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'about_mission_title', 'Our mission'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<ul class="about-list">
|
||||
<li class="about-item">
|
||||
<div class="about-ico">🤝</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_mission_item1_title', 'Easy booking'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_mission_item1_text', 'Book in a few clicks...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_mission_item1_title', 'Easy booking'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_mission_item1_text', 'Book in a few clicks...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="about-item">
|
||||
<div class="about-ico">🛡️</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_mission_item2_title', 'Security'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_mission_item2_text', 'Data privacy and Jitsi...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_mission_item2_title', 'Security'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_mission_item2_text', 'Data privacy and Jitsi...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="about-item">
|
||||
<div class="about-ico">⏱️</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_mission_item3_title', 'Save time'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_mission_item3_text', 'Calendar and online consults...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_mission_item3_title', 'Save time'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_mission_item3_text', 'Calendar and online consults...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2><?= htmlspecialchars(t($translations, 'about_platform_title', 'How the platform works'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'about_platform_title', 'How the platform works'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<ul class="about-list">
|
||||
<li class="about-item">
|
||||
<div class="about-ico">📚</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_platform_item1_title', 'Specialists catalog'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_platform_item1_text', 'Lawyers, notaries...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_platform_item1_title', 'Specialists catalog'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_platform_item1_text', 'Lawyers, notaries...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="about-item">
|
||||
<div class="about-ico">🗓️</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_platform_item2_title', 'Online booking'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_platform_item2_text', 'Choose a time and get email confirmation...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_platform_item2_title', 'Online booking'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_platform_item2_text', 'Choose a time and get email confirmation...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="about-item">
|
||||
<div class="about-ico">💬</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_platform_item3_title', 'Chat before the session'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_platform_item3_text', 'Ask details directly...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_platform_item3_title', 'Chat before the session'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_platform_item3_text', 'Ask details directly...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="about-item">
|
||||
<div class="about-ico">🎥</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_platform_item4_title', 'Video calls'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_platform_item4_text', 'Meetings via Jitsi...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_platform_item4_title', 'Video calls'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_platform_item4_text', 'Meetings via Jitsi...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -220,30 +244,30 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
|
||||
<div class="about-grid" style="margin-top:14px;">
|
||||
<div class="card">
|
||||
<h2><?= htmlspecialchars(t($translations, 'about_clients_title', 'For clients'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_clients_text', 'Fast search and booking...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'about_clients_title', 'For clients'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_clients_text', 'Fast search and booking...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<div class="about-callout">
|
||||
<strong><?= htmlspecialchars(t($translations, 'about_clients_note_label', 'Important:'), ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
<?= htmlspecialchars(t($translations, 'about_clients_note_text', 'uslugi.fr helps you find...'), ENT_QUOTES, 'UTF-8') ?>
|
||||
<strong><?php echo htmlspecialchars(t($translations, 'about_clients_note_label', 'Important:'), ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
<?php echo htmlspecialchars(t($translations, 'about_clients_note_text', 'uslugi.fr helps you find...'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2><?= htmlspecialchars(t($translations, 'about_specialists_title', 'For specialists'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_specialists_text', 'Dashboard, calendar...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'about_specialists_title', 'For specialists'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_specialists_text', 'Dashboard, calendar...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<ul class="about-list">
|
||||
<li class="about-item">
|
||||
<div class="about-ico">🔒</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_specialists_item1_title', 'Data is safe'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_specialists_item1_text', 'Basic security practices...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_specialists_item1_title', 'Data is safe'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_specialists_item1_text', 'Basic security practices...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
<li class="about-item">
|
||||
<div class="about-ico">📈</div>
|
||||
<div>
|
||||
<h4><?= htmlspecialchars(t($translations, 'about_specialists_item2_title', 'Grow your audience'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_specialists_item2_text', 'Visibility in the catalog...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'about_specialists_item2_title', 'Grow your audience'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_specialists_item2_text', 'Visibility in the catalog...'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -253,11 +277,11 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
<br>
|
||||
|
||||
<div class="card">
|
||||
<h2><?= htmlspecialchars(t($translations, 'about_contact_title', 'Contact us'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?= htmlspecialchars(t($translations, 'about_contact_text', 'Have suggestions or questions? Write to us.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'about_contact_title', 'Contact us'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'about_contact_text', 'Have suggestions or questions? Write to us.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<div class="text-start">
|
||||
<a class="btn btn-danger" href="/contact.php" style="padding:12px 16px;border-radius:999px;">
|
||||
<?= htmlspecialchars(t($translations, 'about_contact_btn', 'Write to us'), ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php echo htmlspecialchars(t($translations, 'about_contact_btn', 'Write to us'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -270,7 +294,7 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+6
-3
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
ob_start();
|
||||
require_once __DIR__ . '/../public/includes/init_admin.php';
|
||||
|
||||
// FIX: cast pour comparaison stricte
|
||||
@@ -115,9 +116,9 @@
|
||||
<span class="submenu-arrow">▾</span>
|
||||
</button>
|
||||
<ul class="submenu" hidden>
|
||||
<li onclick="window.open('https://staging.uslugi.fr/matomo/index.php','_blank')">
|
||||
<!--<li onclick="window.open('https://staging.uslugi.fr/matomo/index.php','_blank')">
|
||||
<?php echo h($translations['admin_analytic'] ?? 'Analytics') ?>
|
||||
</li>
|
||||
</li>-->
|
||||
<li onclick="location.href='<?php echo h(admin_url('logs')) ?>'">
|
||||
<?php echo h($translations['afficher_logs'] ?? 'Logs') ?>
|
||||
</li>
|
||||
@@ -292,7 +293,9 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<?php ob_end_flush(); ?>
|
||||
<?php if (ob_get_level() > 0) {
|
||||
ob_end_flush();
|
||||
}?>
|
||||
</body>
|
||||
</html>
|
||||
<?php endif; ?>
|
||||
+140
-133
@@ -1,74 +1,79 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
|
||||
|
||||
$praticien_id = (int) ($_GET['praticien_id'] ?? 0);
|
||||
if ($praticien_id <= 0) {echo "<div class='container py-5'>ID invalide.</div>";exit;}
|
||||
|
||||
$praticien_id = (int)($_GET['praticien_id'] ?? 0);
|
||||
if ($praticien_id <= 0) { echo "<div class='container py-5'>ID invalide.</div>"; exit; }
|
||||
|
||||
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||||
function percent_from_5($n){ $n=max(0,min(5,(float)$n)); return (int)round($n/5*100); }
|
||||
function pseudo_from($prenom,$nom){
|
||||
$p = trim((string)$prenom); $n = trim((string)$nom);
|
||||
$p = $p!=='' ? mb_convert_case($p, MB_CASE_TITLE, 'UTF-8') : 'Client';
|
||||
$i = $n!=='' ? mb_strtoupper(mb_substr($n,0,1,'UTF-8'),'UTF-8') : '';
|
||||
return $i ? ($p.'.'.$i) : $p;
|
||||
}
|
||||
|
||||
// Titre + stats
|
||||
$pp = $pdo->prepare("SELECT titre, prenom, nom FROM praticien WHERE id=?");
|
||||
$pp->execute([$praticien_id]);
|
||||
$pr = $pp->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$pr) { echo "<div class='container py-5'>".$translations['praticien_introuvable']."</div>"; exit; }
|
||||
|
||||
$avg = $pdo->prepare("SELECT ROUND(AVG(note),1) AS m, COUNT(*) AS c FROM avis_praticien WHERE praticien_id=? AND statut='publie'");
|
||||
$avg->execute([$praticien_id]); $stats = $avg->fetch(PDO::FETCH_ASSOC) ?: ['m'=>null,'c'=>0];
|
||||
|
||||
// Form POST
|
||||
$flash = null;
|
||||
if ($_SERVER['REQUEST_METHOD']==='POST' && ($_POST['do'] ?? '')==='add') {
|
||||
if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$flash = ['type'=>'danger','msg'=>$translations['avis_form_err']];
|
||||
} elseif ($_SESSION['role'] !== 'client') {
|
||||
$flash = ['type'=>'danger','msg'=>$translations['non_autorise'] ?? 'Non autorisé'];
|
||||
} else {
|
||||
$note = (int)($_POST['note'] ?? 0);
|
||||
$titre = trim((string)($_POST['titre'] ?? ''));
|
||||
$commentaire = trim((string)($_POST['commentaire'] ?? ''));
|
||||
$visit_date = trim((string)($_POST['visit_date'] ?? ''));
|
||||
|
||||
$ok = $note>=1 && $note<=5 && mb_strlen($commentaire,'UTF-8')>=10;
|
||||
$date_ok = true;
|
||||
if ($visit_date !== '') {
|
||||
$ts = strtotime($visit_date.' 00:00:00');
|
||||
$date_ok = $ts && $ts <= time()+86400; // pas dans le futur
|
||||
function h($s)
|
||||
{return htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8');}
|
||||
function percent_from_5($n)
|
||||
{$n = max(0, min(5, (float) $n));return (int) round($n / 5 * 100);}
|
||||
function pseudo_from($prenom, $nom)
|
||||
{
|
||||
$p = trim((string) $prenom);
|
||||
$n = trim((string) $nom);
|
||||
$p = $p !== '' ? mb_convert_case($p, MB_CASE_TITLE, 'UTF-8') : 'Client';
|
||||
$i = $n !== '' ? mb_strtoupper(mb_substr($n, 0, 1, 'UTF-8'), 'UTF-8') : '';
|
||||
return $i ? ($p . '.' . $i) : $p;
|
||||
}
|
||||
if ($ok && $date_ok) {
|
||||
$st = $pdo->prepare("INSERT INTO avis_praticien (praticien_id, client_id, note, titre, commentaire, visit_date, statut)
|
||||
VALUES (?, ?, ?, ?, ?, ?, 'publie')");
|
||||
$st->execute([$praticien_id, (int)$_SESSION['reference_id'], $note,
|
||||
($titre!==''?$titre:null), ($commentaire!==''?$commentaire:null),
|
||||
($visit_date!==''?$visit_date:null)]);
|
||||
$flash = ['type'=>'success','msg'=>$translations['avis_form_ok']];
|
||||
// refresh stats
|
||||
$avg->execute([$praticien_id]); $stats = $avg->fetch(PDO::FETCH_ASSOC) ?: ['m'=>null,'c'=>0];
|
||||
|
||||
// Titre + stats
|
||||
$pp = $pdo->prepare("SELECT titre, prenom, nom FROM praticien WHERE id=?");
|
||||
$pp->execute([$praticien_id]);
|
||||
$pr = $pp->fetch(PDO::FETCH_ASSOC);
|
||||
if (! $pr) {echo "<div class='container py-5'>" . $translations['praticien_introuvable'] . "</div>";exit;}
|
||||
|
||||
$avg = $pdo->prepare("SELECT ROUND(AVG(note),1) AS m, COUNT(*) AS c FROM avis_praticien WHERE praticien_id=? AND statut='publie'");
|
||||
$avg->execute([$praticien_id]);
|
||||
$stats = $avg->fetch(PDO::FETCH_ASSOC) ?: ['m' => null, 'c' => 0];
|
||||
|
||||
// Form POST
|
||||
$flash = null;
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['do'] ?? '') === 'add') {
|
||||
if (! hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$flash = ['type' => 'danger', 'msg' => $translations['avis_form_err']];
|
||||
} elseif ($_SESSION['role'] !== 'client') {
|
||||
$flash = ['type' => 'danger', 'msg' => $translations['non_autorise'] ?? 'Non autorisé'];
|
||||
} else {
|
||||
$flash = ['type'=>'danger','msg'=>$translations['avis_form_err']];
|
||||
$note = (int) ($_POST['note'] ?? 0);
|
||||
$titre = trim((string) ($_POST['titre'] ?? ''));
|
||||
$commentaire = trim((string) ($_POST['commentaire'] ?? ''));
|
||||
$visit_date = trim((string) ($_POST['visit_date'] ?? ''));
|
||||
|
||||
$ok = $note >= 1 && $note <= 5 && mb_strlen($commentaire, 'UTF-8') >= 10;
|
||||
$date_ok = true;
|
||||
if ($visit_date !== '') {
|
||||
$ts = strtotime($visit_date . ' 00:00:00');
|
||||
$date_ok = $ts && $ts <= time() + 86400; // pas dans le futur
|
||||
}
|
||||
if ($ok && $date_ok) {
|
||||
$st = $pdo->prepare("INSERT INTO avis_praticien (praticien_id, client_id, note, titre, commentaire, visit_date, statut)
|
||||
VALUES (?, ?, ?, ?, ?, ?, 'publie')");
|
||||
$st->execute([$praticien_id, (int) $_SESSION['reference_id'], $note,
|
||||
($titre !== '' ? $titre : null), ($commentaire !== '' ? $commentaire : null),
|
||||
($visit_date !== '' ? $visit_date : null)]);
|
||||
$flash = ['type' => 'success', 'msg' => $translations['avis_form_ok']];
|
||||
// refresh stats
|
||||
$avg->execute([$praticien_id]);
|
||||
$stats = $avg->fetch(PDO::FETCH_ASSOC) ?: ['m' => null, 'c' => 0];
|
||||
} else {
|
||||
$flash = ['type' => 'danger', 'msg' => $translations['avis_form_err']];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination
|
||||
$perPage = 10;
|
||||
$page = max(1, (int)($_GET['page'] ?? 1));
|
||||
$offset = ($page - 1) * $perPage;
|
||||
// Pagination
|
||||
$perPage = 10;
|
||||
$page = max(1, (int) ($_GET['page'] ?? 1));
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$cnt = $pdo->prepare("SELECT COUNT(*) FROM avis_praticien WHERE praticien_id = :pid AND statut = 'publie'");
|
||||
$cnt->execute([':pid' => $praticien_id]);
|
||||
$total = (int)$cnt->fetchColumn();
|
||||
$pages = max(1, (int)ceil($total / $perPage));
|
||||
$cnt = $pdo->prepare("SELECT COUNT(*) FROM avis_praticien WHERE praticien_id = :pid AND statut = 'publie'");
|
||||
$cnt->execute([':pid' => $praticien_id]);
|
||||
$total = (int) $cnt->fetchColumn();
|
||||
$pages = max(1, (int) ceil($total / $perPage));
|
||||
|
||||
$sql = "SELECT a.note, a.titre, a.commentaire, a.visit_date, a.created_at,
|
||||
$sql = "SELECT a.note, a.titre, a.commentaire, a.visit_date, a.created_at,
|
||||
c.prenom, c.nom
|
||||
FROM avis_praticien a
|
||||
LEFT JOIN client c ON c.id = a.client_id
|
||||
@@ -76,58 +81,58 @@ $sql = "SELECT a.note, a.titre, a.commentaire, a.visit_date, a.created_at,
|
||||
ORDER BY a.created_at DESC
|
||||
LIMIT :o, :l";
|
||||
|
||||
$ls = $pdo->prepare($sql);
|
||||
$ls->bindValue(':pid', $praticien_id, PDO::PARAM_INT);
|
||||
$ls->bindValue(':o', (int)$offset, PDO::PARAM_INT);
|
||||
$ls->bindValue(':l', (int)$perPage, PDO::PARAM_INT);
|
||||
$ls->execute();
|
||||
$ls = $pdo->prepare($sql);
|
||||
$ls->bindValue(':pid', $praticien_id, PDO::PARAM_INT);
|
||||
$ls->bindValue(':o', (int) $offset, PDO::PARAM_INT);
|
||||
$ls->bindValue(':l', (int) $perPage, PDO::PARAM_INT);
|
||||
$ls->execute();
|
||||
|
||||
$avis = $ls->fetchAll(PDO::FETCH_ASSOC);
|
||||
$avis = $ls->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ID depuis l'URL (on passe bien ?praticien_id=...)
|
||||
$praticien_id = (int)($_GET['praticien_id'] ?? 0);
|
||||
if ($praticien_id <= 0) { echo "<div class='container py-5'>ID invalide.</div>"; exit; }
|
||||
// ID depuis l'URL (on passe bien ?praticien_id=...)
|
||||
$praticien_id = (int) ($_GET['praticien_id'] ?? 0);
|
||||
if ($praticien_id <= 0) {echo "<div class='container py-5'>ID invalide.</div>";exit;}
|
||||
|
||||
// Charger le praticien
|
||||
$pp = $pdo->prepare("SELECT titre, prenom, nom FROM praticien WHERE id = :id");
|
||||
$pp->execute([':id' => $praticien_id]);
|
||||
$pr = $pp->fetch(PDO::FETCH_ASSOC);
|
||||
// Charger le praticien
|
||||
$pp = $pdo->prepare("SELECT titre, prenom, nom FROM praticien WHERE id = :id");
|
||||
$pp->execute([':id' => $praticien_id]);
|
||||
$pr = $pp->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$pr) {
|
||||
echo "<div class='container py-5'>".$translations['praticien_introuvable']."</div>";
|
||||
exit;
|
||||
}
|
||||
if (! $pr) {
|
||||
echo "<div class='container py-5'>" . $translations['praticien_introuvable'] . "</div>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Définir $name AVANT de l'utiliser
|
||||
$name = trim(
|
||||
($pr['prenom'] ?? '')
|
||||
. ' '
|
||||
. ($pr['nom'] ?? '')
|
||||
);
|
||||
$CSRF = $_SESSION['csrf_token'] ?? '';
|
||||
// Définir $name AVANT de l'utiliser
|
||||
$name = trim(
|
||||
($pr['prenom'] ?? '')
|
||||
. ' '
|
||||
. ($pr['nom'] ?? '')
|
||||
);
|
||||
$CSRF = $_SESSION['csrf_token'] ?? '';
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?= htmlspecialchars($translations['seo_avis_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_avis_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_avis_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_avis_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_avis_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_avis_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<?php include_once __DIR__ . '/includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body class="layout">
|
||||
|
||||
<?php if ($logged):
|
||||
include_header_clean(APP_HTDOCS . '/public/includes/header.php');
|
||||
include_header_clean(APP_HTDOCS . '/public/includes/header.php');
|
||||
else: ?>
|
||||
<!-- Header public (Connexion + “?”) -->
|
||||
<header class="site-header">
|
||||
@@ -148,20 +153,20 @@ else: ?>
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo $translations['btn_se_connecter']?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo $translations['ja_spec']?></span>
|
||||
<span class="d-sm-none"><?php echo $translations['btn_se_connecter'] ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo $translations['ja_spec'] ?></span>
|
||||
</a>
|
||||
<!--<a class="btn-login" href="/connexion.php"><?php echo $translations['ja_spec']?></a>-->
|
||||
<!--<a class="btn-login" href="/connexion.php"><?php echo $translations['ja_spec'] ?></a>-->
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="Помощь">?</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?= $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?= $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?= $translations['nam_pisat'] ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?php echo $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo $translations['nam_pisat'] ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -172,93 +177,95 @@ else: ?>
|
||||
<div class="main">
|
||||
<div class="container py-5">
|
||||
<div class="shadow p-4 rounded bg-light">
|
||||
<h2 class="mb-2"><?= h($translations['avis_titre_page']) ?> — <?= h($name) ?></h2>
|
||||
<h2 class="mb-2"><?php echo h($translations['avis_titre_page']) ?> — <?php echo h($name) ?></h2>
|
||||
|
||||
<div class="d-flex align-items-center gap-3 mb-3">
|
||||
<?php $m=(float)($stats['m'] ?? 0); $c=(int)($stats['c'] ?? 0); $w=percent_from_5($m); ?>
|
||||
<?php $m = (float) ($stats['m'] ?? 0);
|
||||
$c = (int) ($stats['c'] ?? 0);
|
||||
$w = percent_from_5($m); ?>
|
||||
<div class="rating" aria-label="Note">
|
||||
<div class="stars-base">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?= $w ?>%">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?php echo $w ?>%">★★★★★</div>
|
||||
</div>
|
||||
<div class="text-muted"><?= $m ? number_format($m,1,',',' ') : '—' ?>/5 • <?= $c.' '.h($translations['avis_total']) ?></div>
|
||||
<div class="text-muted"><?php echo $m ? number_format($m, 1, ',', ' ') : '—' ?>/5 • <?php echo $c . ' ' . h($translations['avis_total']) ?></div>
|
||||
</div>
|
||||
|
||||
<?php if ($flash): ?>
|
||||
<div class="alert alert-<?= h($flash['type']) ?>"><?= h($flash['msg']) ?></div>
|
||||
<div class="alert alert-<?php echo h($flash['type']) ?>"><?php echo h($flash['msg']) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($_SESSION['role']==='client'): ?>
|
||||
<?php if (($_SESSION['role'] ?? '') === 'client'): ?>
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<h5 class="mb-3"><?= h($translations['avis_form_titre']) ?></h5>
|
||||
<h5 class="mb-3"><?php echo h($translations['avis_form_titre']) ?></h5>
|
||||
<form method="post" class="row g-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label"><?= h($translations['avis_form_note']) ?></label>
|
||||
<label class="form-label"><?php echo h($translations['avis_form_note']) ?></label>
|
||||
<select name="note" class="form-select" required>
|
||||
<?php for($i=5;$i>=1;$i--): ?>
|
||||
<option value="<?= $i ?>"> <?= $i ?> ★</option>
|
||||
<?php for ($i = 5; $i >= 1; $i--): ?>
|
||||
<option value="<?php echo $i ?>"> <?php echo $i ?> ★</option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-4">
|
||||
<label class="form-label"><?= h($translations['avis_form_date_visite']) ?></label>
|
||||
<label class="form-label"><?php echo h($translations['avis_form_date_visite']) ?></label>
|
||||
<input type="date" name="visit_date" class="form-control">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= h($translations['avis_form_titre_lbl']) ?></label>
|
||||
<label class="form-label"><?php echo h($translations['avis_form_titre_lbl']) ?></label>
|
||||
<input type="text" name="titre" class="form-control" maxlength="150">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= h($translations['avis_form_commentaire']) ?></label>
|
||||
<label class="form-label"><?php echo h($translations['avis_form_commentaire']) ?></label>
|
||||
<textarea name="commentaire" class="form-control" rows="4" minlength="10" required></textarea>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<input type="hidden" name="csrf" value="<?= h($CSRF) ?>">
|
||||
<input type="hidden" name="csrf" value="<?php echo h($CSRF) ?>">
|
||||
<input type="hidden" name="do" value="add">
|
||||
<button class="btn btn-primary"><?= h($translations['avis_form_envoyer']) ?></button>
|
||||
<button class="btn btn-primary"><?php echo h($translations['avis_form_envoyer']) ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$avis): ?>
|
||||
<div class="text-muted"><?= h($translations['avis_aucun']) ?></div>
|
||||
<?php else: foreach ($avis as $a): $pw=percent_from_5((float)$a['note']); ?>
|
||||
<?php if (! $avis): ?>
|
||||
<div class="text-muted"><?php echo h($translations['avis_aucun']) ?></div>
|
||||
<?php else: foreach ($avis as $a): $pw = percent_from_5((float) $a['note']); ?>
|
||||
<div class="card shadow-sm mb-3">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start mb-1">
|
||||
<div>
|
||||
<div class="rating mb-1">
|
||||
<div class="stars-base">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?= $pw ?>%">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?php echo $pw ?>%">★★★★★</div>
|
||||
</div>
|
||||
<div class="small text-muted">
|
||||
<strong><?= h(pseudo_from($a['prenom'] ?? '', $a['nom'] ?? '')) ?></strong>
|
||||
<?php if(!empty($a['visit_date'])): ?> • <?= date('d/m/Y', strtotime($a['visit_date'])) ?><?php endif; ?>
|
||||
<strong><?php echo h(pseudo_from($a['prenom'] ?? '', $a['nom'] ?? '')) ?></strong>
|
||||
<?php if (! empty($a['visit_date'])): ?> • <?php echo date('d/m/Y', strtotime($a['visit_date'])) ?><?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="small text-muted"><?= date('d/m/Y', strtotime($a['created_at'])) ?></div>
|
||||
<div class="small text-muted"><?php echo date('d/m/Y', strtotime($a['created_at'])) ?></div>
|
||||
</div>
|
||||
<?php if(!empty($a['titre'])): ?><div class="fw-semibold mb-1"><?= h($a['titre']) ?></div><?php endif; ?>
|
||||
<div><?= nl2br(h($a['commentaire'] ?? '')) ?></div>
|
||||
<?php if (! empty($a['titre'])): ?><div class="fw-semibold mb-1"><?php echo h($a['titre']) ?></div><?php endif; ?>
|
||||
<div><?php echo nl2br(h($a['commentaire'] ?? '')) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; endif; ?>
|
||||
<?php endforeach;endif; ?>
|
||||
|
||||
<?php if ($pages>1): ?>
|
||||
<?php if ($pages > 1): ?>
|
||||
<nav class="mt-3">
|
||||
<?php for ($i=1;$i<=$pages;$i++):
|
||||
$href = '/public/client/avis.php?praticien_id='.$praticien_id.'&page='.$i;
|
||||
$cls = $i===$page ? 'btn btn-sm btn-primary me-1' : 'btn btn-sm btn-outline-primary me-1';
|
||||
<?php for ($i = 1; $i <= $pages; $i++):
|
||||
$href = '/public/client/avis.php?praticien_id=' . $praticien_id . '&page=' . $i;
|
||||
$cls = $i === $page ? 'btn btn-sm btn-primary me-1' : 'btn btn-sm btn-outline-primary me-1';
|
||||
?>
|
||||
<a class="<?= $cls ?>" href="<?= h($href) ?>"><?= $i ?></a>
|
||||
<a class="<?php echo $cls ?>" href="<?php echo h($href) ?>"><?php echo $i ?></a>
|
||||
<?php endfor; ?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="mt-4">
|
||||
<a class="btn btn-outline-secondary" href="/detail_public.php?id=<?= (int)$praticien_id ?>">⬅️ <?= $translations['retour_avis_profil'] ?></a>
|
||||
<a class="btn btn-outline-secondary" href="/detail_public.php?id=<?php echo (int) $praticien_id ?>">⬅️ <?php echo $translations['retour_avis_profil'] ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,7 +273,7 @@ else: ?>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
+22
-22
@@ -1,22 +1,22 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars($translations['seo_choix_inscription_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_choix_inscription_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_choix_inscription_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_choix_inscription_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_choix_inscription_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_choix_inscription_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<?php include_once __DIR__ . '/includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
@@ -42,13 +42,13 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="Помощь">?</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?= $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?= $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?= $translations['nam_pisat'] ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?php echo $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo $translations['nam_pisat'] ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@@ -61,15 +61,15 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
</style>
|
||||
<div class="main">
|
||||
<div class="container p-4 shadow-sm bg-white rounded-3" style="min-width: 380px; width: 100%; margin:40px auto;">
|
||||
<h2 class="text-center mb-4"><?= $translations['choix_type_inscription'] ?></h2>
|
||||
<h2 class="text-center mb-4"><?php echo $translations['choix_type_inscription'] ?></h2>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-4">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title"><?= $translations['choix_client_titre'] ?></h5>
|
||||
<p class="card-text"><?= $translations['choix_client_texte'] ?></p>
|
||||
<a href="/inscription_client.php" class="btn btn-primary"><?= $translations['btn_inscription_client'] ?></a>
|
||||
<h5 class="card-title"><?php echo $translations['choix_client_titre'] ?></h5>
|
||||
<p class="card-text"><?php echo $translations['choix_client_texte'] ?></p>
|
||||
<a href="/inscription_client.php" class="btn btn-primary"><?php echo $translations['btn_inscription_client'] ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,9 +77,9 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<div class="col-md-4 mt-4 mt-md-0">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title"><?= $translations['choix_pro_titre'] ?></h5>
|
||||
<p class="card-text"><?= $translations['choix_pro_texte'] ?></p>
|
||||
<a href="/inscription_praticien.php" class="btn btn-secondary"><?= $translations['btn_inscription_pro'] ?></a>
|
||||
<h5 class="card-title"><?php echo $translations['choix_pro_titre'] ?></h5>
|
||||
<p class="card-text"><?php echo $translations['choix_pro_texte'] ?></p>
|
||||
<a href="/inscription_praticien.php" class="btn btn-secondary"><?php echo $translations['btn_inscription_pro'] ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,7 +89,7 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
+264
-220
@@ -1,219 +1,263 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
declare (strict_types = 1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void {
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
/* ---------- Utils ---------- */
|
||||
function envget(string $k): string {
|
||||
return trim((string)($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? ''));
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string {
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') return $fallback;
|
||||
return (string)$val;
|
||||
}
|
||||
|
||||
$LOG_DIR = __DIR__ . '/tmp';
|
||||
$LOG_FILE = $LOG_DIR . '/contact.log';
|
||||
if (!is_dir($LOG_DIR)) { @mkdir($LOG_DIR, 0770, true); } // dossier local, pas servi publiquement
|
||||
|
||||
/* ---------- CSRF ---------- */
|
||||
if (empty($_SESSION['pub_csrf'])) {
|
||||
$_SESSION['pub_csrf'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$CSRF = $_SESSION['pub_csrf'];
|
||||
|
||||
// --- reCAPTCHA v2 (lecture robuste) ---
|
||||
$rcCfg = [];
|
||||
$cfgPath = __DIR__ . '/includes/recaptcha.php';
|
||||
if (is_file($cfgPath)) {
|
||||
$rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...']
|
||||
}
|
||||
|
||||
$RECAPTCHA_SITE_KEY = trim((string)($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? ''));
|
||||
$RECAPTCHA_SECRET_KEY = trim((string)($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? ''));
|
||||
|
||||
// Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs
|
||||
$HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20);
|
||||
$HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20);
|
||||
|
||||
// (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1
|
||||
if (($_GET['testcaptcha'] ?? '') === '1') $HAS_SITE = true;
|
||||
|
||||
/* ---------- État page ---------- */
|
||||
$errors = [];
|
||||
$sent = false;
|
||||
|
||||
/* ---------- POST ---------- */
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
|
||||
|
||||
// CSRF
|
||||
if (!hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.');
|
||||
}
|
||||
|
||||
// Honeypot anti-bot
|
||||
if (!empty($_POST['website'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_spam', 'Spam suspected.');
|
||||
}
|
||||
|
||||
// Données utilisateur
|
||||
$prenom = trim($_POST['prenom'] ?? '');
|
||||
$nom = trim($_POST['nom'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$sujet = trim($_POST['sujet'] ?? '');
|
||||
$message = trim($_POST['message'] ?? '');
|
||||
|
||||
// Validations
|
||||
if (mb_strlen($prenom) < 2) $errors[] = t($translations, 'contact_err_prenom', 'Please enter your first name.');
|
||||
if (mb_strlen($nom) < 2) $errors[] = t($translations, 'contact_err_nom', 'Please enter your last name.');
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.');
|
||||
if (mb_strlen($sujet) < 3) $errors[] = t($translations, 'contact_err_sujet', 'Subject is too short.');
|
||||
if (mb_strlen($message) < 10) $errors[] = t($translations, 'contact_err_message', 'Message is too short.');
|
||||
|
||||
// reCAPTCHA serveur
|
||||
if ($HAS_SECRET) {
|
||||
$token = $_POST['g-recaptcha-response'] ?? '';
|
||||
if ($token === '') {
|
||||
$errors[] = t($translations, 'contact_err_captcha_required', 'Please confirm you are not a robot.');
|
||||
} else {
|
||||
$resp = @file_get_contents(
|
||||
'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($RECAPTCHA_SECRET_KEY) .
|
||||
'&response=' . urlencode($token) .
|
||||
'&remoteip=' . urlencode($_SERVER['REMOTE_ADDR'] ?? '')
|
||||
);
|
||||
$ver = $resp ? json_decode($resp, true) : ['success' => false];
|
||||
if (empty($ver['success'])) $errors[] = t($translations, 'contact_err_captcha_failed', 'reCAPTCHA verification failed.');
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Envoi
|
||||
if (!$errors) {
|
||||
$to = 'contact@uslugi.fr';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — ');
|
||||
$subject = $subjectPrefix . $sujet;
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr');
|
||||
$lblName = t($translations, 'contact_mail_label_name', 'Name');
|
||||
$lblEmail = t($translations, 'contact_mail_label_email', 'Email');
|
||||
$lblSubject = t($translations, 'contact_mail_label_subject', 'Subject');
|
||||
$lblMessage = t($translations, 'contact_mail_label_message', 'Message');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$html = '
|
||||
<h3>'.htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8').'</h3>
|
||||
<p><strong>'.htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8').':</strong> '.htmlspecialchars($prenom).' '.htmlspecialchars($nom).'</p>
|
||||
<p><strong>'.htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8').':</strong> '.htmlspecialchars($email).'</p>
|
||||
<p><strong>'.htmlspecialchars($lblSubject, ENT_QUOTES, 'UTF-8').':</strong> '.htmlspecialchars($sujet).'</p>
|
||||
<p><strong>'.htmlspecialchars($lblMessage, ENT_QUOTES, 'UTF-8').':</strong><br>'.nl2br(htmlspecialchars($message)).'</p>
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
/* ---------- Utils ---------- */
|
||||
function envget(string $k): string
|
||||
{
|
||||
return trim((string) ($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? ''));
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string
|
||||
{
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return (string) $val;
|
||||
}
|
||||
|
||||
$LOG_DIR = __DIR__ . '/tmp';
|
||||
$LOG_FILE = $LOG_DIR . '/contact.log';
|
||||
if (! is_dir($LOG_DIR)) {@mkdir($LOG_DIR, 0770, true);} // dossier local, pas servi publiquement
|
||||
|
||||
/* ---------- CSRF ---------- */
|
||||
if (empty($_SESSION['pub_csrf'])) {
|
||||
$_SESSION['pub_csrf'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$CSRF = $_SESSION['pub_csrf'];
|
||||
|
||||
// --- reCAPTCHA v2 (lecture robuste) ---
|
||||
$rcCfg = [];
|
||||
$cfgPath = __DIR__ . '/includes/recaptcha.php';
|
||||
if (is_file($cfgPath)) {
|
||||
$rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...']
|
||||
}
|
||||
|
||||
$RECAPTCHA_SITE_KEY = trim((string) ($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? ''));
|
||||
$RECAPTCHA_SECRET_KEY = trim((string) ($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? ''));
|
||||
|
||||
// Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs
|
||||
$HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20);
|
||||
$HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20);
|
||||
|
||||
// (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1
|
||||
if (($_GET['testcaptcha'] ?? '') === '1') {
|
||||
$HAS_SITE = true;
|
||||
}
|
||||
|
||||
/* ---------- État page ---------- */
|
||||
$errors = [];
|
||||
$sent = false;
|
||||
|
||||
/* ---------- POST ---------- */
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
|
||||
|
||||
// CSRF
|
||||
if (! hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.');
|
||||
}
|
||||
|
||||
// Honeypot anti-bot
|
||||
if (! empty($_POST['website'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_spam', 'Spam suspected.');
|
||||
}
|
||||
|
||||
// Données utilisateur
|
||||
$prenom = trim($_POST['prenom'] ?? '');
|
||||
$nom = trim($_POST['nom'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$sujet = trim($_POST['sujet'] ?? '');
|
||||
$message = trim($_POST['message'] ?? '');
|
||||
|
||||
// Validations
|
||||
if (mb_strlen($prenom) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_prenom', 'Please enter your first name.');
|
||||
}
|
||||
|
||||
if (mb_strlen($nom) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_nom', 'Please enter your last name.');
|
||||
}
|
||||
|
||||
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.');
|
||||
}
|
||||
|
||||
if (mb_strlen($sujet) < 3) {
|
||||
$errors[] = t($translations, 'contact_err_sujet', 'Subject is too short.');
|
||||
}
|
||||
|
||||
if (mb_strlen($message) < 10) {
|
||||
$errors[] = t($translations, 'contact_err_message', 'Message is too short.');
|
||||
}
|
||||
|
||||
// reCAPTCHA serveur
|
||||
if ($HAS_SECRET) {
|
||||
$token = $_POST['g-recaptcha-response'] ?? '';
|
||||
if ($token === '') {
|
||||
$errors[] = t($translations, 'contact_err_captcha_required', 'Please confirm you are not a robot.');
|
||||
} else {
|
||||
$resp = @file_get_contents(
|
||||
'https://www.google.com/recaptcha/api/siteverify?secret=' . urlencode($RECAPTCHA_SECRET_KEY) .
|
||||
'&response=' . urlencode($token) .
|
||||
'&remoteip=' . urlencode($_SERVER['REMOTE_ADDR'] ?? '')
|
||||
);
|
||||
$ver = $resp ? json_decode($resp, true) : ['success' => false];
|
||||
if (empty($ver['success'])) {
|
||||
$errors[] = t($translations, 'contact_err_captcha_failed', 'reCAPTCHA verification failed.');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Envoi
|
||||
if (! $errors) {
|
||||
$to = 'contact@uslugi.fr';
|
||||
|
||||
$subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — ');
|
||||
$subject = $subjectPrefix . $sujet;
|
||||
|
||||
$mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr');
|
||||
$lblName = t($translations, 'contact_mail_label_name', 'Name');
|
||||
$lblEmail = t($translations, 'contact_mail_label_email', 'Email');
|
||||
$lblSubject = t($translations, 'contact_mail_label_subject', 'Subject');
|
||||
$lblMessage = t($translations, 'contact_mail_label_message', 'Message');
|
||||
|
||||
$html = '
|
||||
<h3>' . htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8') . '</h3>
|
||||
<p><strong>' . htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($prenom) . ' ' . htmlspecialchars($nom) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($email) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblSubject, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($sujet) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblMessage, ENT_QUOTES, 'UTF-8') . ':</strong><br>' . nl2br(htmlspecialchars($message)) . '</p>
|
||||
';
|
||||
|
||||
$text = $mailH3 . "\n"
|
||||
. $lblName . ": $prenom $nom\n"
|
||||
. $lblEmail . ": $email\n"
|
||||
. $lblSubject . ": $sujet\n\n"
|
||||
. $lblMessage . ":\n$message\n";
|
||||
$text = $mailH3 . "\n"
|
||||
. $lblName . ": $prenom $nom\n"
|
||||
. $lblEmail . ": $email\n"
|
||||
. $lblSubject . ": $sujet\n\n"
|
||||
. $lblMessage . ":\n$message\n";
|
||||
|
||||
try {
|
||||
// From et Reply-To (tableaux) comme attendus par ton wrapper
|
||||
$fromEmail = 'no-reply@uslugi.fr';
|
||||
$fromName = 'USLUGI.FR';
|
||||
try {
|
||||
// From et Reply-To (tableaux) comme attendus par ton wrapper
|
||||
$fromEmail = 'no-reply@uslugi.fr';
|
||||
$fromName = 'USLUGI.FR';
|
||||
|
||||
$replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr';
|
||||
$replyName = trim($prenom.' '.$nom) ?: 'USLUGI.FR';
|
||||
$replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr';
|
||||
$replyName = trim($prenom . ' ' . $nom) ?: 'USLUGI.FR';
|
||||
|
||||
// Appel wrapper: retourne [bool $ok, ?string $err]
|
||||
[$ok, $err] = uslugi_mail(
|
||||
$to,
|
||||
$subject,
|
||||
$html,
|
||||
$text,
|
||||
[
|
||||
'from' => [$fromEmail, $fromName],
|
||||
'reply_to' => [$replyEmail, $replyName],
|
||||
// 'bcc' => ['tonmail@gmail.com'],
|
||||
]
|
||||
);
|
||||
// Appel wrapper: retourne [bool $ok, ?string $err]
|
||||
[$ok, $err] = uslugi_mail(
|
||||
$to,
|
||||
$subject,
|
||||
$html,
|
||||
$text,
|
||||
[
|
||||
'from' => [$fromEmail, $fromName],
|
||||
'reply_to' => [$replyEmail, $replyName],
|
||||
// 'bcc' => ['tonmail@gmail.com'],
|
||||
]
|
||||
);
|
||||
|
||||
if ($ok !== true) {
|
||||
throw new RuntimeException('Wrapper mail send failed.');
|
||||
}
|
||||
if ($ok !== true) {
|
||||
throw new RuntimeException('Wrapper mail send failed.');
|
||||
}
|
||||
|
||||
// OK
|
||||
$sent = true;
|
||||
$_POST = [];
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] OK to=%s subj=%s reply=%s ip=%s\n",
|
||||
date('c'), $to, $sujet, $email, $_SERVER['REMOTE_ADDR'] ?? '-'
|
||||
), FILE_APPEND);
|
||||
// OK
|
||||
$sent = true;
|
||||
$_POST = [];
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] OK to=%s subj=%s reply=%s ip=%s\n",
|
||||
date('c'), $to, $sujet, $email, $_SERVER['REMOTE_ADDR'] ?? '-'
|
||||
), FILE_APPEND);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
error_log('MAIL ERROR: ' . $e->getMessage());
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] ERR to=%s subj=%s\n",
|
||||
date('c'), $to, $sujet
|
||||
), FILE_APPEND);
|
||||
} catch (Throwable $e) {
|
||||
error_log('MAIL ERROR: ' . $e->getMessage());
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] ERR to=%s subj=%s\n",
|
||||
date('c'), $to, $sujet
|
||||
), FILE_APPEND);
|
||||
|
||||
// Message utilisateur générique (jamais d’info sensible à l’écran)
|
||||
$errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.');
|
||||
// Message utilisateur générique (jamais d’info sensible à l’écran)
|
||||
$errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (string)$lang : 'ru';
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru';
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<html lang="<?php echo htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_contact_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_contact_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_contact_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_contact_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
/* HERO bleu et cadre */
|
||||
.hero-contact{ background:#8CA9FF; padding: clamp(16px,4vw,32px); }
|
||||
@@ -242,9 +286,9 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
</head>
|
||||
<body>
|
||||
<?php if (is_client_logged_in()): ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php else: ?>
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
@@ -264,8 +308,8 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8')?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8')?></span>
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -275,15 +319,15 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8')?>">
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -297,65 +341,65 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
<section class="hero-contact">
|
||||
<div class="container contact-wrap">
|
||||
<div class="contact-frame">
|
||||
<h1><?= htmlspecialchars(t($translations, 'contact_h1', 'Contact us'), ENT_QUOTES, 'UTF-8') ?></h1>
|
||||
<p class="muted"><?= htmlspecialchars(t($translations, 'contact_intro', 'Fill the form — we will reply as soon as possible.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
<h1><?php echo htmlspecialchars(t($translations, 'contact_h1', 'Contact us'), ENT_QUOTES, 'UTF-8') ?></h1>
|
||||
<p class="muted"><?php echo htmlspecialchars(t($translations, 'contact_intro', 'Fill the form — we will reply as soon as possible.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
|
||||
<?php if (!empty($errors)): ?>
|
||||
<?php if (! empty($errors)): ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?= implode('<br>', array_map(static fn($s) => htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'), $errors)) ?>
|
||||
<?php echo implode('<br>', array_map(static fn($s) => htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8'), $errors)) ?>
|
||||
</div>
|
||||
<?php elseif ($sent): ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?= htmlspecialchars(t($translations, 'contact_success_sent', 'Thank you! Your message has been sent.'), ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php echo htmlspecialchars(t($translations, 'contact_success_sent', 'Thank you! Your message has been sent.'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="" novalidate>
|
||||
<input type="hidden" name="csrf" value="<?= htmlspecialchars($CSRF, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<input type="hidden" name="csrf" value="<?php echo htmlspecialchars($CSRF, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<!-- Honeypot invisible -->
|
||||
<input type="text" name="website" autocomplete="off" tabindex="-1"
|
||||
style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_nom', 'Last name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_nom', 'Last name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="text" name="nom" class="form-control"
|
||||
value="<?= htmlspecialchars($_POST['nom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
value="<?php echo htmlspecialchars($_POST['nom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_prenom', 'First name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_prenom', 'First name'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="text" name="prenom" class="form-control"
|
||||
value="<?= htmlspecialchars($_POST['prenom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
value="<?php echo htmlspecialchars($_POST['prenom'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_email', 'Email'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_email', 'Email'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="email" name="email" class="form-control" inputmode="email"
|
||||
placeholder="<?= htmlspecialchars(t($translations, 'contact_email_placeholder', 'name@example.com'), ENT_QUOTES, 'UTF-8') ?>"
|
||||
value="<?= htmlspecialchars($_POST['email'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
placeholder="<?php echo htmlspecialchars(t($translations, 'contact_email_placeholder', 'name@example.com'), ENT_QUOTES, 'UTF-8') ?>"
|
||||
value="<?php echo htmlspecialchars($_POST['email'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_sujet', 'Subject'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_sujet', 'Subject'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<input type="text" name="sujet" class="form-control"
|
||||
value="<?= htmlspecialchars($_POST['sujet'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
value="<?php echo htmlspecialchars($_POST['sujet'] ?? '', ENT_QUOTES, 'UTF-8') ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label class="form-label"><?= htmlspecialchars(t($translations, 'contact_label_message', 'Message'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<textarea name="message" class="form-control" required><?= htmlspecialchars($_POST['message'] ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
|
||||
<label class="form-label"><?php echo htmlspecialchars(t($translations, 'contact_label_message', 'Message'), ENT_QUOTES, 'UTF-8') ?></label>
|
||||
<textarea name="message" class="form-control" required><?php echo htmlspecialchars($_POST['message'] ?? '', ENT_QUOTES, 'UTF-8') ?></textarea>
|
||||
</div>
|
||||
|
||||
<?php if ($HAS_SITE): ?>
|
||||
<div class="col-12">
|
||||
<div class="g-recaptcha" data-sitekey="<?= htmlspecialchars($RECAPTCHA_SITE_KEY, ENT_QUOTES, 'UTF-8') ?>"></div>
|
||||
<div class="g-recaptcha" data-sitekey="<?php echo htmlspecialchars($RECAPTCHA_SITE_KEY, ENT_QUOTES, 'UTF-8') ?>"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="col-12 d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-red">
|
||||
<?= htmlspecialchars(t($translations, 'contact_btn_submit', 'Send'), ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php echo htmlspecialchars(t($translations, 'contact_btn_submit', 'Send'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -368,7 +412,7 @@ $langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string)($lang ?? '')) ? (str
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+142
-133
@@ -1,87 +1,94 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
|
||||
$SPEC_CANON = require __DIR__ . '/includes/spec_map.php';
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
|
||||
$SPEC_CANON = require __DIR__ . '/includes/spec_map.php';
|
||||
|
||||
$canon = $SPEC_CANON[$lang] ?? [];
|
||||
$canon = $SPEC_CANON[$lang] ?? [];
|
||||
|
||||
// ------- (ton code existant) -------
|
||||
$praticien_id = (int) ($_GET['id'] ?? 0);
|
||||
if ($praticien_id <= 0) {echo "<div class='container py-5'>ID invalide.</div>";exit;}
|
||||
|
||||
function h($s)
|
||||
{return htmlspecialchars((string) $s, ENT_QUOTES, 'UTF-8');}
|
||||
function percent_from_5($note)
|
||||
{$n = max(0, min(5, (float) $note));return (int) round($n / 5 * 100);}
|
||||
function pseudo_from($prenom, $nom)
|
||||
{
|
||||
$p = trim((string) $prenom);
|
||||
$n = trim((string) $nom);
|
||||
$p = $p !== '' ? mb_convert_case($p, MB_CASE_TITLE, 'UTF-8') : 'Client';
|
||||
$i = $n !== '' ? mb_strtoupper(mb_substr($nom, 0, 1, 'UTF-8'), 'UTF-8') : '';
|
||||
return $i ? ($p . '.' . $i) : $p;
|
||||
}
|
||||
function video_thumb_info(?string $url): ?array
|
||||
{
|
||||
if (! $url || ! trim($url)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ------- (ton code existant) -------
|
||||
$praticien_id = (int)($_GET['id'] ?? 0);
|
||||
if ($praticien_id <= 0) { echo "<div class='container py-5'>ID invalide.</div>"; exit; }
|
||||
$u = trim($url);
|
||||
if (preg_match('~(?:youtube\.com/(?:watch\?v=|embed/|shorts/)|youtu\.be/)([A-Za-z0-9_-]{6,})~i', $u, $m)) {
|
||||
$id = $m[1];return ['provider' => 'youtube', 'id' => $id, 'thumb' => "https://i.ytimg.com/vi/$id/hqdefault.jpg"];
|
||||
}
|
||||
if (preg_match('~dailymotion\.com/video/([A-Za-z0-9]+)|dai\.ly/([A-Za-z0-9]+)~i', $u, $m)) {
|
||||
$id = $m[1] ?: $m[2];return ['provider' => 'dailymotion', 'id' => $id, 'thumb' => "https://www.dailymotion.com/thumbnail/video/$id"];
|
||||
}
|
||||
$path = parse_url($u, PHP_URL_PATH) ?? '';if (preg_match('~\.(mp4|webm|ogg)$~i', $path)) {return ['provider' => 'file', 'id' => null, 'thumb' => null];}
|
||||
if (stripos($u, 'vimeo.com') !== false) {return ['provider' => 'vimeo', 'id' => null, 'thumb' => null];}
|
||||
return ['provider' => 'other', 'id' => null, 'thumb' => null];
|
||||
}
|
||||
|
||||
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
|
||||
function percent_from_5($note){ $n = max(0,min(5,(float)$note)); return (int)round($n/5*100); }
|
||||
function pseudo_from($prenom,$nom){
|
||||
$p = trim((string)$prenom); $n = trim((string)$nom);
|
||||
$p = $p!=='' ? mb_convert_case($p, MB_CASE_TITLE, 'UTF-8') : 'Client';
|
||||
$i = $n!=='' ? mb_strtoupper(mb_substr($nom,0,1,'UTF-8'),'UTF-8') : '';
|
||||
return $i ? ($p.'.'.$i) : $p;
|
||||
}
|
||||
function video_thumb_info(?string $url): ?array {
|
||||
if (!$url || !trim($url)) return null; $u = trim($url);
|
||||
if (preg_match('~(?:youtube\.com/(?:watch\?v=|embed/|shorts/)|youtu\.be/)([A-Za-z0-9_-]{6,})~i',$u,$m)){
|
||||
$id=$m[1]; return ['provider'=>'youtube','id'=>$id,'thumb'=>"https://i.ytimg.com/vi/$id/hqdefault.jpg"];
|
||||
}
|
||||
if (preg_match('~dailymotion\.com/video/([A-Za-z0-9]+)|dai\.ly/([A-Za-z0-9]+)~i',$u,$m)){
|
||||
$id=$m[1] ?: $m[2]; return ['provider'=>'dailymotion','id'=>$id,'thumb'=>"https://www.dailymotion.com/thumbnail/video/$id"];
|
||||
}
|
||||
$path=parse_url($u,PHP_URL_PATH)??''; if(preg_match('~\.(mp4|webm|ogg)$~i',$path)){ return ['provider'=>'file','id'=>null,'thumb'=>null]; }
|
||||
if (stripos($u,'vimeo.com')!==false){ return ['provider'=>'vimeo','id'=>null,'thumb'=>null]; }
|
||||
return ['provider'=>'other','id'=>null,'thumb'=>null];
|
||||
}
|
||||
|
||||
// 1) Praticien
|
||||
$st = $pdo->prepare("SELECT id, titre, nom, prenom, telephone, adresse, ville, code_postal, specialite, presentation, photo, video, disponibilite
|
||||
// 1) Praticien
|
||||
$st = $pdo->prepare("SELECT id, titre, nom, prenom, telephone, adresse, ville, code_postal, specialite, presentation, photo, video, disponibilite
|
||||
FROM praticien WHERE id = ?");
|
||||
$st->execute([$praticien_id]);
|
||||
$p = $st->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$p) { echo "<div class='container py-5'>".$translations['praticien_introuvable']."</div>"; exit; }
|
||||
$st->execute([$praticien_id]);
|
||||
$p = $st->fetch(PDO::FETCH_ASSOC);
|
||||
if (! $p) {echo "<div class='container py-5'>" . $translations['praticien_introuvable'] . "</div>";exit;}
|
||||
|
||||
$name = $name = trim($p['prenom'] . ' ' . $p['nom']);
|
||||
$photo = !empty($p['photo']) ? "/public/uploads/".ltrim($p['photo'],'/') : "/public/uploads/img/user_placeholder.png";
|
||||
$name = $name = trim($p['prenom'] . ' ' . $p['nom']);
|
||||
$photo = ! empty($p['photo']) ? "/public/uploads/" . ltrim($p['photo'], '/') : "/public/uploads/img/user_placeholder.png";
|
||||
|
||||
// 2) Vidéos additionnelles
|
||||
$vs = $pdo->prepare("SELECT id, url, title, ordre FROM praticien_video WHERE praticien_id=? ORDER BY ordre ASC, id DESC");
|
||||
$vs->execute([$praticien_id]);
|
||||
$videos = $vs->fetchAll(PDO::FETCH_ASSOC);
|
||||
// 2) Vidéos additionnelles
|
||||
$vs = $pdo->prepare("SELECT id, url, title, ordre FROM praticien_video WHERE praticien_id=? ORDER BY ordre ASC, id DESC");
|
||||
$vs->execute([$praticien_id]);
|
||||
$videos = $vs->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 3) Avis: moyenne + total + dernier
|
||||
$avg = $pdo->prepare("SELECT ROUND(AVG(note),1) AS m, COUNT(*) AS c FROM avis_praticien WHERE praticien_id=? AND statut='publie'");
|
||||
$avg->execute([$praticien_id]);
|
||||
$stats = $avg->fetch(PDO::FETCH_ASSOC) ?: ['m'=>null,'c'=>0];
|
||||
// 3) Avis: moyenne + total + dernier
|
||||
$avg = $pdo->prepare("SELECT ROUND(AVG(note),1) AS m, COUNT(*) AS c FROM avis_praticien WHERE praticien_id=? AND statut='publie'");
|
||||
$avg->execute([$praticien_id]);
|
||||
$stats = $avg->fetch(PDO::FETCH_ASSOC) ?: ['m' => null, 'c' => 0];
|
||||
|
||||
$last = $pdo->prepare("SELECT a.note,a.titre,a.commentaire,a.visit_date,a.created_at,c.prenom,c.nom
|
||||
$last = $pdo->prepare("SELECT a.note,a.titre,a.commentaire,a.visit_date,a.created_at,c.prenom,c.nom
|
||||
FROM avis_praticien a
|
||||
LEFT JOIN client c ON c.id=a.client_id
|
||||
WHERE a.praticien_id=? AND a.statut='publie'
|
||||
ORDER BY a.created_at DESC LIMIT 1");
|
||||
$last->execute([$praticien_id]);
|
||||
$lrow = $last->fetch(PDO::FETCH_ASSOC);
|
||||
$last->execute([$praticien_id]);
|
||||
$lrow = $last->fetch(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?= $name . " - " . $p['specialite'] . " - " . htmlspecialchars($translations['seo_detail_public_title'], ENT_QUOTES, 'UTF-8')?></title>
|
||||
<meta name="description" content="<?= $name . " - " . $p['specialite'] . " - " . $p['presentation'] ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_detail_public_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo $name . " - " . $p['specialite'] . " - " . htmlspecialchars($translations['seo_detail_public_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo $name . " - " . $p['specialite'] . " - " . $p['presentation'] ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_detail_public_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<?php include_once __DIR__ . '/includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body class="layout">
|
||||
|
||||
<?php if ($logged):
|
||||
include_header_clean(APP_HTDOCS . '/public/includes/header.php');
|
||||
include_header_clean(APP_HTDOCS . '/public/includes/header.php');
|
||||
else: ?>
|
||||
<!-- Header public (Connexion + “?”) -->
|
||||
<header class="site-header">
|
||||
@@ -102,20 +109,20 @@ else: ?>
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo $translations['btn_se_connecter']?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo $translations['ja_spec']?></span>
|
||||
<span class="d-sm-none"><?php echo $translations['btn_se_connecter'] ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo $translations['ja_spec'] ?></span>
|
||||
</a>
|
||||
<!--<a class="btn-login" href="/connexion.php"><?php echo $translations['ja_spec']?></a>-->
|
||||
<!--<a class="btn-login" href="/connexion.php"><?php echo $translations['ja_spec'] ?></a>-->
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="Помощь">?</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?= $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?= $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?= $translations['nam_pisat'] ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?php echo $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo $translations['nam_pisat'] ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -130,75 +137,75 @@ else: ?>
|
||||
<!-- Cadre 1 : Infos -->
|
||||
<section class="panel">
|
||||
<div class="info-scroll">
|
||||
<h2 class="pro-name"><?= h($name) ?></h2>
|
||||
<?php if($p['specialite']): ?><div><strong><?= h($translations['dp_specialite']) ?>:</strong> <?= h($p['specialite']) ?></div><?php endif; ?>
|
||||
<!--<?php if($p['telephone']): ?><div><strong><?= h($translations['dp_telephone']) ?>:</strong> <?= h($p['telephone']) ?></div><?php endif; ?>-->
|
||||
<?php if($p['titre']): ?><div><strong><?= h($translations['tarif_consultation']) ?>:</strong> <?= h($p['titre']) ?></div><?php endif; ?>
|
||||
<?php if($p['disponibilite']): ?><div><strong><?= h($translations['moyens_payement']) ?>:</strong> <?= h($p['disponibilite']) ?></div><?php endif; ?>
|
||||
<?php if($p['adresse']): ?><div><strong><?= h($translations['dp_adresse']) ?>:</strong> <?= nl2br(h($p['adresse'])) ?></div><?php endif; ?>
|
||||
<?php if($p['ville'] || $p['code_postal']): ?><div><strong><?= h($translations['dp_ville_cp']) ?>:</strong> <?= h(trim(($p['ville']??'').' '.($p['code_postal']??''))) ?></div><?php endif; ?>
|
||||
<?php if($p['presentation']): ?><div class="mt-3"><strong><?= h($translations['dp_description']) ?>:</strong><br><?= nl2br(h($p['presentation'])) ?></div><?php endif; ?>
|
||||
<h2 class="pro-name"><?php echo h($name) ?></h2>
|
||||
<?php if ($p['specialite']): ?><div><strong><?php echo h($translations['dp_specialite']) ?>:</strong> <?php echo h($p['specialite']) ?></div><?php endif; ?>
|
||||
<!--<?php if ($p['telephone']): ?><div><strong><?php echo h($translations['dp_telephone']) ?>:</strong> <?php echo h($p['telephone']) ?></div><?php endif; ?>-->
|
||||
<?php if ($p['titre']): ?><div><strong><?php echo h($translations['tarif_consultation']) ?>:</strong> <?php echo h($p['titre']) ?></div><?php endif; ?>
|
||||
<?php if ($p['disponibilite']): ?><div><strong><?php echo h($translations['moyens_payement']) ?>:</strong> <?php echo h($p['disponibilite']) ?></div><?php endif; ?>
|
||||
<?php if ($p['adresse']): ?><div><strong><?php echo h($translations['dp_adresse']) ?>:</strong> <?php echo nl2br(h($p['adresse'])) ?></div><?php endif; ?>
|
||||
<?php if ($p['ville'] || $p['code_postal']): ?><div><strong><?php echo h($translations['dp_ville_cp']) ?>:</strong> <?php echo h(trim(($p['ville'] ?? '') . ' ' . ($p['code_postal'] ?? ''))) ?></div><?php endif; ?>
|
||||
<?php if ($p['presentation']): ?><div class="mt-3"><strong><?php echo h($translations['dp_description']) ?>:</strong><br><?php echo nl2br(h($p['presentation'])) ?></div><?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Centre : grande photo -->
|
||||
<section class="big-photo">
|
||||
<img class="img-fluid w-100" src="<?= h($photo) ?>" alt="Photo">
|
||||
<img class="img-fluid w-100" src="<?php echo h($photo) ?>" alt="Photo">
|
||||
</section>
|
||||
|
||||
<!-- Cadre 2 : Vidéos -->
|
||||
<?php if($p['video'] != ''){ ?>
|
||||
<?php if ($p['video'] != '') {?>
|
||||
<aside class="panel">
|
||||
<h2 class="pro-name"><?= h($translations['dp_videos']) ?></h2>
|
||||
<h2 class="pro-name"><?php echo h($translations['dp_videos']) ?></h2>
|
||||
<div class="vlist">
|
||||
<?php
|
||||
$alt = h($translations['video_alt'] ?? 'Vidéo');
|
||||
$printed = false;
|
||||
$alt = h($translations['video_alt'] ?? 'Vidéo');
|
||||
$printed = false;
|
||||
|
||||
// Petite fonction d'affichage d’une vignette
|
||||
$printThumb = function($provider, $id, $thumb, $rawUrl) use ($alt){
|
||||
if (in_array($provider, ['youtube','dailymotion']) && $id){
|
||||
echo '<a href="#" class="vitem d-block pro-video"
|
||||
// Petite fonction d'affichage d’une vignette
|
||||
$printThumb = function ($provider, $id, $thumb, $rawUrl) use ($alt) {
|
||||
if (in_array($provider, ['youtube', 'dailymotion']) && $id) {
|
||||
echo '<a href="#" class="vitem d-block pro-video"
|
||||
data-bs-toggle="modal" data-bs-target="#videoModal"
|
||||
data-provider="'.h($provider).'" data-id="'.h($id).'">';
|
||||
echo $thumb
|
||||
? '<img src="'.h($thumb).'" alt="'.$alt.'" loading="lazy">'
|
||||
: '<img src="/public/uploads/img/video_placeholder.jpg" alt="'.$alt.'" loading="lazy">';
|
||||
echo '</a>';
|
||||
} else {
|
||||
$safe = h($rawUrl);
|
||||
echo '<a class="vitem d-block" href="'.$safe.'" target="_blank" rel="noopener">';
|
||||
echo $thumb
|
||||
? '<img src="'.h($thumb).'" alt="'.$alt.'" loading="lazy">'
|
||||
: '<img src="/public/uploads/img/video_placeholder.jpg" alt="'.$alt.'" loading="lazy">';
|
||||
echo '</a>';
|
||||
}
|
||||
};
|
||||
data-provider="' . h($provider) . '" data-id="' . h($id) . '">';
|
||||
echo $thumb
|
||||
? '<img src="' . h($thumb) . '" alt="' . $alt . '" loading="lazy">'
|
||||
: '<img src="/public/uploads/img/video_placeholder.jpg" alt="' . $alt . '" loading="lazy">';
|
||||
echo '</a>';
|
||||
} else {
|
||||
$safe = h($rawUrl);
|
||||
echo '<a class="vitem d-block" href="' . $safe . '" target="_blank" rel="noopener">';
|
||||
echo $thumb
|
||||
? '<img src="' . h($thumb) . '" alt="' . $alt . '" loading="lazy">'
|
||||
: '<img src="/public/uploads/img/video_placeholder.jpg" alt="' . $alt . '" loading="lazy">';
|
||||
echo '</a>';
|
||||
}
|
||||
};
|
||||
|
||||
if (!empty($p['video'])) {
|
||||
$vi = video_thumb_info($p['video']);
|
||||
$thumb = $vi['thumb'] ?? null;
|
||||
$prov = $vi['provider'] ?? null;
|
||||
$vid = $vi['id'] ?? null;
|
||||
$printThumb($prov, $vid, $thumb, $p['video']);
|
||||
$printed = true;
|
||||
}
|
||||
foreach ($videos as $v) {
|
||||
$vi = video_thumb_info($v['url']);
|
||||
$thumb = $vi['thumb'] ?? null;
|
||||
$prov = $vi['provider'] ?? null;
|
||||
$vid = $vi['id'] ?? null;
|
||||
$printThumb($prov, $vid, $thumb, $v['url']);
|
||||
$printed = true;
|
||||
}
|
||||
if (!$printed) {
|
||||
echo '<div class="vitem"><img src="/public/uploads/img/video_placeholder.jpg" alt="'.$alt.'"></div>';
|
||||
//echo '<div class="text-muted small mt-1">'.h($translations['dp_aucune_video']).'</div>';
|
||||
}
|
||||
?>
|
||||
if (! empty($p['video'])) {
|
||||
$vi = video_thumb_info($p['video']);
|
||||
$thumb = $vi['thumb'] ?? null;
|
||||
$prov = $vi['provider'] ?? null;
|
||||
$vid = $vi['id'] ?? null;
|
||||
$printThumb($prov, $vid, $thumb, $p['video']);
|
||||
$printed = true;
|
||||
}
|
||||
foreach ($videos as $v) {
|
||||
$vi = video_thumb_info($v['url']);
|
||||
$thumb = $vi['thumb'] ?? null;
|
||||
$prov = $vi['provider'] ?? null;
|
||||
$vid = $vi['id'] ?? null;
|
||||
$printThumb($prov, $vid, $thumb, $v['url']);
|
||||
$printed = true;
|
||||
}
|
||||
if (! $printed) {
|
||||
echo '<div class="vitem"><img src="/public/uploads/img/video_placeholder.jpg" alt="' . $alt . '"></div>';
|
||||
//echo '<div class="text-muted small mt-1">'.h($translations['dp_aucune_video']).'</div>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</aside>
|
||||
<?php } ?>
|
||||
<?php }?>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -207,14 +214,16 @@ else: ?>
|
||||
<!-- Cadre 3 : Note -->
|
||||
<div class="card shadow-sm p-3">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<?php $m=(float)($stats['m'] ?? 0); $c=(int)($stats['c'] ?? 0); $w=percent_from_5($m); ?>
|
||||
<?php $m = (float) ($stats['m'] ?? 0);
|
||||
$c = (int) ($stats['c'] ?? 0);
|
||||
$w = percent_from_5($m); ?>
|
||||
<div class="rating" aria-label="Note moyenne">
|
||||
<div class="stars-base">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?= $w ?>%">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?php echo $w ?>%">★★★★★</div>
|
||||
</div>
|
||||
<div>
|
||||
<div><strong><?= h($translations['avis_note_moy']) ?>:</strong> <?= $m ? number_format($m,1,',',' ') : '—' ?>/5</div>
|
||||
<div class="text-muted">(<?= $c.' '.h($translations['avis_total']) ?>)</div>
|
||||
<div><strong><?php echo h($translations['avis_note_moy']) ?>:</strong> <?php echo $m ? number_format($m, 1, ',', ' ') : '—' ?>/5</div>
|
||||
<div class="text-muted">(<?php echo $c . ' ' . h($translations['avis_total']) ?>)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -222,31 +231,31 @@ else: ?>
|
||||
<!-- Cadre 4 : Dernier avis -->
|
||||
<div class="card shadow-sm p-3 avis-card">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<strong><?= h($translations['avis_dernier']) ?></strong>
|
||||
<a class="btn btn-link p-0" href="/avis_public.php?praticien_id=<?= (int)$praticien_id ?>">
|
||||
<?= h($translations['avis_lire_tous']) ?>
|
||||
<strong><?php echo h($translations['avis_dernier']) ?></strong>
|
||||
<a class="btn btn-link p-0" href="/avis_public.php?praticien_id=<?php echo (int) $praticien_id ?>">
|
||||
<?php echo h($translations['avis_lire_tous']) ?>
|
||||
</a>
|
||||
</div>
|
||||
<?php if ($lrow): ?>
|
||||
<?php $lw=percent_from_5((float)$lrow['note']); ?>
|
||||
<?php $lw = percent_from_5((float) $lrow['note']); ?>
|
||||
<div class="rating mb-1">
|
||||
<div class="stars-base">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?= $lw ?>%">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?php echo $lw ?>%">★★★★★</div>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<?= h(pseudo_from($lrow['prenom'] ?? '', $lrow['nom'] ?? '')) ?>
|
||||
<?php if(!empty($lrow['visit_date'])): ?> • <?= date('d/m/Y', strtotime($lrow['visit_date'])) ?><?php endif; ?>
|
||||
<?php echo h(pseudo_from($lrow['prenom'] ?? '', $lrow['nom'] ?? '')) ?>
|
||||
<?php if (! empty($lrow['visit_date'])): ?> • <?php echo date('d/m/Y', strtotime($lrow['visit_date'])) ?><?php endif; ?>
|
||||
</div>
|
||||
<div><?= nl2br(h(mb_strimwidth((string)$lrow['commentaire'],0,320,'…','UTF-8'))) ?></div>
|
||||
<div><?php echo nl2br(h(mb_strimwidth((string) $lrow['commentaire'], 0, 320, '…', 'UTF-8'))) ?></div>
|
||||
<?php else: ?>
|
||||
<div class="text-muted"><?= h($translations['avis_aucun']) ?></div>
|
||||
<div class="text-muted"><?php echo h($translations['avis_aucun']) ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Bouton RDV -->
|
||||
<div class="text-end">
|
||||
<a class="btn btn-danger btn-lg" href="/public/client/reserver_rdv.php?praticien_id=<?= (int)$praticien_id ?>">
|
||||
<?= h($translations['dp_btn_rdv']) ?>
|
||||
<a class="btn btn-danger btn-lg" href="/public/client/reserver_rdv.php?praticien_id=<?php echo (int) $praticien_id ?>">
|
||||
<?php echo h($translations['dp_btn_rdv']) ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -259,8 +268,8 @@ else: ?>
|
||||
<div class="modal-dialog modal-dialog-centered modal-xl">
|
||||
<div class="modal-content border-0 shadow-lg rounded-4">
|
||||
<div class="modal-header border-0">
|
||||
<h5 class="modal-title" id="videoModalLabel"><?= h($translations['video_titre'] ?? 'Vidéo') ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?= h($translations['fermer'] ?? 'Fermer') ?>"></button>
|
||||
<h5 class="modal-title" id="videoModalLabel"><?php echo h($translations['video_titre'] ?? 'Vidéo') ?></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="<?php echo h($translations['fermer'] ?? 'Fermer') ?>"></button>
|
||||
</div>
|
||||
<div class="modal-body pt-0">
|
||||
<div class="ratio ratio-16x9 rounded-3 overflow-hidden bg-black">
|
||||
@@ -272,7 +281,7 @@ else: ?>
|
||||
</div>
|
||||
<div class="modal-footer border-0">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
<?= h($translations['fermer'] ?? 'Fermer') ?>
|
||||
<?php echo h($translations['fermer'] ?? 'Fermer') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -309,7 +318,7 @@ else: ?>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,639 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
/* ---------- Utils ---------- */
|
||||
function envget(string $k): string
|
||||
{
|
||||
return trim((string) ($_ENV[$k] ?? $_SERVER[$k] ?? getenv($k) ?? ''));
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string
|
||||
{
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return (string) $val;
|
||||
}
|
||||
|
||||
$LOG_DIR = __DIR__ . '/tmp';
|
||||
$LOG_FILE = $LOG_DIR . '/contact.log';
|
||||
if (! is_dir($LOG_DIR)) {@mkdir($LOG_DIR, 0770, true);} // dossier local, pas servi publiquement
|
||||
|
||||
/* ---------- CSRF ---------- */
|
||||
if (empty($_SESSION['pub_csrf'])) {
|
||||
$_SESSION['pub_csrf'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
$CSRF = $_SESSION['pub_csrf'];
|
||||
|
||||
// --- reCAPTCHA v2 (lecture robuste) ---
|
||||
$rcCfg = [];
|
||||
$cfgPath = __DIR__ . '/includes/recaptcha.php';
|
||||
if (is_file($cfgPath)) {
|
||||
$rcCfg = require $cfgPath; // ['site' => '...', 'secret' => '...']
|
||||
}
|
||||
|
||||
$RECAPTCHA_SITE_KEY = trim((string) ($rcCfg['site'] ?? envget('RECAPTCHA_SITE_KEY') ?? ''));
|
||||
$RECAPTCHA_SECRET_KEY = trim((string) ($rcCfg['secret'] ?? envget('RECAPTCHA_SECRET_KEY') ?? ''));
|
||||
|
||||
// Considère la clé "valide" si longueur réaliste (>= 20) – évite les faux négatifs
|
||||
$HAS_SITE = (strlen($RECAPTCHA_SITE_KEY) >= 20);
|
||||
$HAS_SECRET = (strlen($RECAPTCHA_SECRET_KEY) >= 20);
|
||||
|
||||
// (optionnel) forcer l’affichage en test: /contact.php?testcaptcha=1
|
||||
if (($_GET['testcaptcha'] ?? '') === '1') {
|
||||
$HAS_SITE = true;
|
||||
}
|
||||
|
||||
/* ---------- État page ---------- */
|
||||
$errors = [];
|
||||
$sent = false;
|
||||
|
||||
/* ---------- POST ---------- */
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
|
||||
|
||||
// CSRF
|
||||
if (! hash_equals($_SESSION['pub_csrf'] ?? '', $_POST['csrf'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_security', 'Security error. Refresh and try again.');
|
||||
}
|
||||
|
||||
// Honeypot anti-bot (Corrigé avec 'company' pour correspondre à votre HTML)
|
||||
if (! empty($_POST['company'] ?? '')) {
|
||||
$errors[] = t($translations, 'contact_err_spam', 'Spam suspected.');
|
||||
}
|
||||
|
||||
// Données utilisateur
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$profession = trim($_POST['profession'] ?? '');
|
||||
$city = trim($_POST['city'] ?? '');
|
||||
$country = trim($_POST['country'] ?? '');
|
||||
$phone = trim($_POST['phone'] ?? '');
|
||||
$email = trim($_POST['email'] ?? '');
|
||||
$site = trim($_POST['site'] ?? '');
|
||||
$reason = trim($_POST['reason'] ?? '');
|
||||
|
||||
// Validations
|
||||
if (mb_strlen($name) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_name', 'Please enter your name.');
|
||||
}
|
||||
|
||||
if (mb_strlen($profession) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_profession', 'Please enter your profession.');
|
||||
}
|
||||
|
||||
if (mb_strlen($city) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_city', 'Please enter your city.');
|
||||
}
|
||||
|
||||
if (mb_strlen($country) < 2) {
|
||||
$errors[] = t($translations, 'contact_err_country', 'Please enter your country.');
|
||||
}
|
||||
if ($phone === '' && $email === '' && $site === '') {
|
||||
$errors[] = t($translations, 'contact_err_contact', 'Please provide at least one contact (phone, e-mail or website).');
|
||||
}
|
||||
|
||||
if ($email !== '' && ! filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = t($translations, 'contact_err_email', 'Please enter a valid email.');
|
||||
}
|
||||
|
||||
if (mb_strlen($reason) < 10) {
|
||||
$errors[] = t($translations, 'contact_err_reason', 'Reason is too short.');
|
||||
}
|
||||
|
||||
// Envoi
|
||||
if (! $errors) {
|
||||
$to = 'contact@uslugi.fr';
|
||||
|
||||
$subjectPrefix = t($translations, 'contact_send_subject_prefix', 'Contact form message — ');
|
||||
$subject = $subjectPrefix . $site;
|
||||
|
||||
$mailH3 = t($translations, 'contact_mail_h3', 'New message from uslugi.fr');
|
||||
$lblName = t($translations, 'contact_mail_label_name', 'Name');
|
||||
$lblProfession = t($translations, 'contact_mail_label_profession', 'Profession');
|
||||
$lblCity = t($translations, 'contact_mail_label_city', 'City');
|
||||
$lblCountry = t($translations, 'contact_mail_label_country', 'Country');
|
||||
$lblPhone = t($translations, 'contact_mail_label_phone', 'Phone');
|
||||
$lblEmail = t($translations, 'contact_mail_label_email', 'Email');
|
||||
$lblSite = t($translations, 'contact_mail_label_site', 'Site');
|
||||
$lblReason = t($translations, 'contact_mail_label_reason', 'Reason');
|
||||
|
||||
$html = '
|
||||
<h3>' . htmlspecialchars($mailH3, ENT_QUOTES, 'UTF-8') . '</h3>
|
||||
<p><strong>' . htmlspecialchars($lblName, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($name) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblProfession, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($profession) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblCity, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($city) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblCountry, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($country) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblPhone, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($phone) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblEmail, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($email) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblSite, ENT_QUOTES, 'UTF-8') . ':</strong> ' . htmlspecialchars($site) . '</p>
|
||||
<p><strong>' . htmlspecialchars($lblReason, ENT_QUOTES, 'UTF-8') . ':</strong><br>' . nl2br(htmlspecialchars($reason)) . '</p>';
|
||||
|
||||
$text = $mailH3 . "\n"
|
||||
. $lblName . ": $name\n"
|
||||
. $lblProfession . ": $profession\n"
|
||||
. $lblCity . ": $city\n"
|
||||
. $lblCountry . ": $country\n"
|
||||
. $lblPhone . ": $phone\n"
|
||||
. $lblEmail . ": $email\n"
|
||||
. $lblSite . ": $site\n\n"
|
||||
. $lblReason . ":\n$reason\n";
|
||||
|
||||
try {
|
||||
// From et Reply-To (tableaux) comme attendus par ton wrapper
|
||||
$fromEmail = 'no-reply@uslugi.fr';
|
||||
$fromName = 'USLUGI.FR';
|
||||
|
||||
$replyEmail = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'contact@uslugi.fr';
|
||||
$replyName = trim($name . ' ' . $profession) ?: 'USLUGI.FR';
|
||||
|
||||
// Appel wrapper: retourne [bool $ok, ?string $err]
|
||||
[$ok, $err] = uslugi_mail(
|
||||
$to,
|
||||
$subject,
|
||||
$html,
|
||||
$text,
|
||||
[
|
||||
'from' => [$fromEmail, $fromName],
|
||||
'reply_to' => [$replyEmail, $replyName],
|
||||
// 'bcc' => ['tonmail@gmail.com'],
|
||||
]
|
||||
);
|
||||
|
||||
if ($ok !== true) {
|
||||
throw new RuntimeException('Wrapper mail send failed.');
|
||||
}
|
||||
|
||||
// OK
|
||||
$sent = true;
|
||||
$_POST = [];
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] OK to=%s subj=%s reply=%s ip=%s\n",
|
||||
date('c'), $to, $site, $email, $_SERVER['REMOTE_ADDR'] ?? '-'
|
||||
), FILE_APPEND);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
error_log('MAIL ERROR: ' . $e->getMessage());
|
||||
@file_put_contents($LOG_FILE, sprintf(
|
||||
"[%s] ERR to=%s subj=%s\n",
|
||||
date('c'), $to, $site
|
||||
), FILE_APPEND);
|
||||
|
||||
// Message utilisateur générique (jamais d’info sensible à l’écran)
|
||||
$errors[] = t($translations, 'contact_err_send_failed', 'Failed to send message. Please try later.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru';
|
||||
/*
|
||||
* Formulaire de recommandation — à intégrer dans la page existante.
|
||||
* Conserve les clés form_index_* déjà utilisées pour le titre, l'introduction,
|
||||
* le bouton, les messages et les champs communs.
|
||||
*/
|
||||
|
||||
$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' => '',
|
||||
'profession' => '',
|
||||
'city' => '',
|
||||
'country' => '',
|
||||
'contact' => '',
|
||||
'reason' => '',
|
||||
];
|
||||
|
||||
function form_index_value(array $old, string $key): string
|
||||
{
|
||||
return htmlspecialchars((string) ($old[$key] ?? ''), ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
function form_index_text(array $translations, string $key, string $fallback): string
|
||||
{
|
||||
$value = $translations[$key] ?? '';
|
||||
return htmlspecialchars($value !== '' ? (string) $value : $fallback, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?php echo htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?php echo htmlspecialchars($translations['seo_contact_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_contact_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_contact_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
/* HERO bleu et cadre */
|
||||
.hero-contact{ background:#8CA9FF; padding: clamp(16px,4vw,32px); }
|
||||
.contact-wrap{ max-width:980px; margin:0 auto; font-family:"Montserrat",system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif; }
|
||||
.contact-frame{
|
||||
background:#fff; border:1px solid #DFE4FF; border-radius:22px;
|
||||
box-shadow:0 16px 40px rgba(56,55,139,.14);
|
||||
padding:clamp(16px,3vw,28px);
|
||||
}
|
||||
.contact h1{ font-size:clamp(24px,5.6vw,34px); margin:0 0 10px; }
|
||||
.contact p.muted{ color:#6b7280; margin:0 0 14px; }
|
||||
/* Forme */
|
||||
.form-label{ font-weight:600; }
|
||||
.form-control{ border-radius:12px; padding:12px 14px; }
|
||||
textarea.form-control{ min-height: 180px; }
|
||||
/* Bouton rouge arrondi */
|
||||
.btn-red{
|
||||
--bs-btn-bg:#E03C3F; --bs-btn-border-color:#E03C3F;
|
||||
--bs-btn-hover-bg:#c53637; --bs-btn-hover-border-color:#c53637;
|
||||
--bs-btn-active-bg:#a62e2f; --bs-btn-active-border-color:#a62e2f;
|
||||
--bs-btn-hover-color:#fff;
|
||||
color:#fff; border-radius:9999px; padding:12px 22px;
|
||||
}
|
||||
</style>
|
||||
<?php include_once __DIR__ . '/includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php if (is_client_logged_in()): ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php else: ?>
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
<div class="header-left">
|
||||
<div class="brand">
|
||||
<a href="/index.php"><img src="/public/uploads/img/logo_u.png"
|
||||
alt="uslugi.fr"
|
||||
class="logo-mobile"></a>
|
||||
|
||||
<a href="/index.php"><img src="/public/uploads/img/logo.png"
|
||||
alt="uslugi.fr"
|
||||
class="logo-desktop"></a>
|
||||
</div>
|
||||
<div class="lang-switch">
|
||||
<?php require __DIR__ . '/includes/menu_langue.php'; ?>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
<button
|
||||
class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
<section class="concierge-section" id="concierge-form">
|
||||
<div class="concierge-inner">
|
||||
|
||||
<div class="concierge-heading">
|
||||
<span class="label">
|
||||
<?php echo form_index_text($translations, 'recom_badge', 'Бесплатно · Без регистрации'); ?>
|
||||
</span>
|
||||
<h2>
|
||||
<?php echo form_index_text($translations, 'recom_title', 'Хотите порекомендовать нужного специалиста?'); ?>
|
||||
</h2>
|
||||
<p>
|
||||
<?php echo form_index_text($translations, 'recom_intro', 'Опишите подробно специалиста, которого вы знаете, и мы свяжемся с ним, чтобы предложить разместить профиль на нашей платформе.'); ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="concierge-card">
|
||||
<div class="card-stripe"></div>
|
||||
|
||||
<?php
|
||||
if ($sent) {
|
||||
$form_index_status = 'success';
|
||||
} elseif ($errors) {
|
||||
$form_index_status = 'error';
|
||||
$form_index_message = implode(' ', $errors);
|
||||
$form_index_old = [
|
||||
'name' => $name ?? '', 'profession' => $profession ?? '',
|
||||
'city' => $city ?? '', 'country' => $country ?? '',
|
||||
'phone' => $phone ?? '', 'email' => $email ?? '',
|
||||
'site' => $site ?? '', 'reason' => $reason ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
if ($form_index_status === 'success'): ?>
|
||||
<div class="card-success" id="successState">
|
||||
<div class="success-circle">✓</div>
|
||||
<h3><?php echo form_index_text($translations, 'form_index_success_title', 'Спасибо за рекомендацию!'); ?></h3>
|
||||
<p><?php echo form_index_text($translations, 'recom_success_text', 'Ваша рекомендация отправлена.'); ?></p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="card-form" id="formState">
|
||||
|
||||
<?php if ($form_index_status === 'error' && $form_index_message !== ''): ?>
|
||||
<div class="form-alert form-alert-error" role="alert">
|
||||
<?php echo htmlspecialchars($form_index_message, ENT_QUOTES, 'UTF-8'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post" action="">
|
||||
<input type="hidden" name="csrf" value="<?php echo htmlspecialchars($CSRF, ENT_QUOTES, 'UTF-8'); ?>">
|
||||
<input type="hidden" name="form_index" value="1">
|
||||
|
||||
<div class="honeypot" 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 field-full">
|
||||
<label for="f-name">
|
||||
<?php echo form_index_text($translations, 'recom_fullname_label', 'Имя и фамилия'); ?>
|
||||
<span class="req">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-name"
|
||||
name="name"
|
||||
autocomplete="name"
|
||||
required
|
||||
value="<?php echo form_index_value($form_index_old, 'name'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['name']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_fullname_placeholder', 'Имя и фамилия специалиста'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field field-full">
|
||||
<label for="f-profession">
|
||||
<?php echo form_index_text($translations, 'recom_profession_label', 'Профессия / чем занимается'); ?>
|
||||
<span class="req">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-profession"
|
||||
name="profession"
|
||||
required
|
||||
value="<?php echo form_index_value($form_index_old, 'profession'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['profession']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_profession_placeholder', 'Например: адвокат, врач, переводчик…'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="f-city">
|
||||
<?php echo form_index_text($translations, 'recom_location_label', 'Город'); ?>
|
||||
<span class="req">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-city"
|
||||
name="city"
|
||||
required
|
||||
value="<?php echo form_index_value($form_index_old, 'city'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['city']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_location_placeholder', 'Город'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label for="f-country">
|
||||
<?php echo form_index_text($translations, 'recom_location_label', 'Страна'); ?>
|
||||
<span class="req">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-country"
|
||||
name="country"
|
||||
required
|
||||
value="<?php echo form_index_value($form_index_old, 'country'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['country']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_location_placeholder', 'Страна'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field field-full">
|
||||
<label for="f-phone">
|
||||
<?php echo form_index_text($translations, 'recom_phone_label', 'Телефон / e-mail / сайт (что известно)'); ?>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-phone"
|
||||
name="phone"
|
||||
value="<?php echo form_index_value($form_index_old, 'phone'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['phone']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_phone_placeholder', 'Телефон'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field field-full">
|
||||
<label for="f-email">
|
||||
<?php echo form_index_text($translations, 'recom_email_label', 'Телефон / e-mail / сайт (что известно)'); ?>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-email"
|
||||
name="email"
|
||||
value="<?php echo form_index_value($form_index_old, 'email'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['email']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_email_placeholder', 'E-mail'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="field field-full">
|
||||
<label for="f-site">
|
||||
<?php echo form_index_text($translations, 'recom_website_label', 'Телефон / e-mail / сайт (что известно)'); ?>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="f-site"
|
||||
name="site"
|
||||
value="<?php echo form_index_value($form_index_old, 'site'); ?>"
|
||||
class="<?php echo ! empty($form_index_errors['site']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_website_placeholder', 'Адрес сайта'); ?>"
|
||||
>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="field field-full">
|
||||
<label for="f-reason">
|
||||
<?php echo form_index_text($translations, 'recom_reason_label', 'Почему рекомендуете?'); ?>
|
||||
<span class="req">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="f-reason"
|
||||
name="reason"
|
||||
required
|
||||
maxlength="1000"
|
||||
class="<?php echo ! empty($form_index_errors['reason']) ? 'error' : ''; ?>"
|
||||
placeholder="<?php echo form_index_text($translations, 'recom_reason_placeholder', 'Коротко расскажите, почему вы рекомендуете этого специалиста…'); ?>"
|
||||
><?php echo form_index_value($form_index_old, 'reason'); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn-submit" type="submit">
|
||||
<?php echo form_index_text($translations, 'recom_submit', 'Отправить рекомендацию'); ?>
|
||||
</button>
|
||||
|
||||
<p class="form-note">
|
||||
<?php echo form_index_text($translations, 'recom_note', 'Пожалуйста, указывайте только известную вам информацию.'); ?>
|
||||
</p>
|
||||
</form>
|
||||
</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: .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: 0 0 10px;
|
||||
}
|
||||
.concierge-heading p {
|
||||
font-size: 14px; 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,.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; min-width: 0; }
|
||||
.field label {
|
||||
font-size: 12px; font-weight: 600; color: #1e2d5a;
|
||||
letter-spacing: .03em; text-transform: uppercase;
|
||||
}
|
||||
.field label .req { color: #2e4db0; margin-left: 2px; }
|
||||
.card-form input, .card-form textarea {
|
||||
box-sizing: border-box; width: 100%; font-family: 'Montserrat', sans-serif;
|
||||
font-size: 14px; color: #1e2d5a; background: #f7f8fc;
|
||||
border: 1.5px solid #dde3f0; border-radius: 8px; padding: 11px 14px;
|
||||
outline: none; transition: border-color .18s,background .18s,box-shadow .18s;
|
||||
}
|
||||
.card-form input::placeholder, .card-form textarea::placeholder { color: #b0b8cc; }
|
||||
.card-form input:focus, .card-form textarea:focus {
|
||||
border-color: #2e4db0; background: #fff; box-shadow: 0 0 0 3px rgba(46,77,176,.09);
|
||||
}
|
||||
.card-form input.error, .card-form textarea.error { border-color: #d73a3a; background: #fff8f8; }
|
||||
.card-form textarea { resize: vertical; min-height: 100px; line-height: 1.6; }
|
||||
.btn-submit {
|
||||
box-sizing: border-box; width: 100%; margin-top: 20px; background: #e03c3f; color: #fff;
|
||||
font-family: 'Montserrat', sans-serif; font-size: 14px; font-weight: 700;
|
||||
letter-spacing: .04em; border: 0; border-radius: 999px; padding: 14px 24px;
|
||||
cursor: pointer; transition: background .18s,transform .12s,box-shadow .18s;
|
||||
}
|
||||
.btn-submit:hover { background: #c93639; box-shadow: 0 6px 20px rgba(30,45,90,.22); }
|
||||
.btn-submit:active { transform: translateY(1px); }
|
||||
.form-note { text-align: center; font-size: 11px; color: #6b7280; margin: 12px 0 0; line-height: 1.5; }
|
||||
.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 { padding: 52px 36px; text-align: center; }
|
||||
.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: #fff;
|
||||
}
|
||||
.card-success h3 { font-size: 20px; font-weight: 700; color: #1e2d5a; margin: 0 0 10px; }
|
||||
.card-success p { font-size: 14px; color: #6b7280; line-height: 1.65; max-width: 380px; margin: 0 auto; }
|
||||
.honeypot { position: absolute; left: -9999px; opacity: 0; pointer-events: none; }
|
||||
@media (max-width: 540px) {
|
||||
.card-form { padding: 24px 20px 28px; }
|
||||
.fields-grid { grid-template-columns: 1fr; }
|
||||
.field-full { grid-column: auto; }
|
||||
.card-success { padding: 36px 20px; }
|
||||
.concierge-section { padding: 36px 16px; }
|
||||
}
|
||||
</style>
|
||||
+86
-86
@@ -5,87 +5,87 @@
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
function t(array $translations, string $key, string $fallback = ''): string
|
||||
{
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') {
|
||||
return $fallback;
|
||||
}
|
||||
$val = $translations[$key] ?? '';
|
||||
if ($val === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return (string) $val;
|
||||
return (string) $val;
|
||||
}
|
||||
|
||||
// Lang HTML
|
||||
$langHtml = preg_match('~^[a-z]{2}(-[A-Z]{2})?$~', (string) ($lang ?? '')) ? (string) $lang : 'ru';
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?php echo htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8')?>">
|
||||
<html lang="<?php echo htmlspecialchars($langHtml, ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?php echo htmlspecialchars($translations['seo_how_it_work_title'], ENT_QUOTES, 'UTF-8')?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_how_it_work_desc'], ENT_QUOTES, 'UTF-8')?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_how_it_work_keywords'], ENT_QUOTES, 'UTF-8')?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_how_it_work_title'], ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_how_it_work_desc'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_how_it_work_keywords'], ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
.howitworks { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#6b7280; --card:#fff; --border:#e5e7eb; }
|
||||
.howitworks { font-family: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; color:var(--text); }
|
||||
@@ -135,9 +135,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<?php if (is_client_logged_in()): ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/public/includes/init_pr_cl.php';
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php'); ?>
|
||||
<?php else: ?>
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
@@ -157,8 +157,8 @@
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8')?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8')?></span>
|
||||
<span class="d-sm-none"><?php echo htmlspecialchars($translations['btn_se_connecter'] ?? 'Connexion', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo htmlspecialchars($translations['ja_spec'] ?? 'Je suis spécialiste', ENT_QUOTES, 'UTF-8') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -168,15 +168,15 @@
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8')?>">
|
||||
aria-label="<?php echo htmlspecialchars(t($translations, 'howitworks_help_aria', 'Help'), ENT_QUOTES, 'UTF-8') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8')?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo htmlspecialchars($translations['kak_rabotaet'] ?? 'Как это работает', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo htmlspecialchars($translations['pro_nas'] ?? 'О нас', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo htmlspecialchars($translations['faq'] ?? 'FAQ', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo htmlspecialchars($translations['nam_pisat'] ?? 'Написать нам', ENT_QUOTES, 'UTF-8') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -193,111 +193,111 @@
|
||||
<div class="wrap">
|
||||
|
||||
<div class="card" style="margin-bottom:18px;">
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'howitworks_short_title', 'How it works'), ENT_QUOTES, 'UTF-8')?></h2>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'howitworks_short_title', 'How it works'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
|
||||
<div class="hiw-steps">
|
||||
<div class="step">
|
||||
<div class="step-icon">📝</div>
|
||||
<div>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step1_title', 'Registration'), ENT_QUOTES, 'UTF-8')?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step1_text', 'Create your account in minutes.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step1_title', 'Registration'), ENT_QUOTES, 'UTF-8') ?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step1_text', 'Create your account in minutes.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-icon">🔎</div>
|
||||
<div>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step2_title', 'Choose a specialist'), ENT_QUOTES, 'UTF-8')?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step2_text', 'Find an expert and pick a time.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step2_title', 'Choose a specialist'), ENT_QUOTES, 'UTF-8') ?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step2_text', 'Find an expert and pick a time.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-icon">✉️</div>
|
||||
<div>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step3_title', 'Confirmation'), ENT_QUOTES, 'UTF-8')?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step3_text', 'Receive an email confirmation and pay the specialist directly.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step3_title', 'Confirmation'), ENT_QUOTES, 'UTF-8') ?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step3_text', 'Receive an email confirmation and pay the specialist directly.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="step">
|
||||
<div class="step-icon">🎥</div>
|
||||
<div>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step4_title', 'Online consultation'), ENT_QUOTES, 'UTF-8')?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step4_text', 'Happens on our website via Jitsi.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h3><?php echo htmlspecialchars(t($translations, 'howitworks_step4_title', 'Online consultation'), ENT_QUOTES, 'UTF-8') ?></h3>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_step4_text', 'Happens on our website via Jitsi.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'howitworks_long_title', 'How uslugi.fr works'), ENT_QUOTES, 'UTF-8')?></h2>
|
||||
<h2><?php echo htmlspecialchars(t($translations, 'howitworks_long_title', 'How uslugi.fr works'), ENT_QUOTES, 'UTF-8') ?></h2>
|
||||
|
||||
<p class="hiw-intro">
|
||||
<?php echo htmlspecialchars(t($translations, 'howitworks_long_intro', 'We built the website to help you find a trusted Russian-speaking specialist in France and get a consultation easily.'), ENT_QUOTES, 'UTF-8')?>
|
||||
<?php echo htmlspecialchars(t($translations, 'howitworks_long_intro', 'We built the website to help you find a trusted Russian-speaking specialist in France and get a consultation easily.'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</p>
|
||||
|
||||
<ul class="hiw-list">
|
||||
<li class="hiw-item">
|
||||
<div class="dot">1</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item1_title', 'Registration'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item1_text', 'Create your personal account in minutes.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item1_title', 'Registration'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item1_text', 'Create your personal account in minutes.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="hiw-item">
|
||||
<div class="dot">2</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item2_title', 'Choose a specialist'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item2_text', 'In the catalog: lawyers, notaries, consultants, psychologists and translators. Each specialist has a calendar with available dates and times.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item2_title', 'Choose a specialist'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item2_text', 'In the catalog: lawyers, notaries, consultants, psychologists and translators. Each specialist has a calendar with available dates and times.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="hiw-item">
|
||||
<div class="dot">3</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item3_title', 'Booking'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item3_text', 'Pick a time and receive an email confirmation.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item3_title', 'Booking'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item3_text', 'Pick a time and receive an email confirmation.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="hiw-item">
|
||||
<div class="dot">4</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item4_title', 'Payment'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item4_text', 'Pay the specialist directly — we do not take any commission.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item4_title', 'Payment'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item4_text', 'Pay the specialist directly — we do not take any commission.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="hiw-item">
|
||||
<div class="dot">5</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item5_title', 'Chat'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item5_text', 'Before the consultation, you can уточнить детали in chat with the expert.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item5_title', 'Chat'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item5_text', 'Before the consultation, you can уточнить детали in chat with the expert.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="hiw-item">
|
||||
<div class="dot">6</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item6_title', 'Online meeting'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item6_text', 'The consultation takes place via Jitsi on our website — just open the link.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item6_title', 'Online meeting'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item6_text', 'The consultation takes place via Jitsi on our website — just open the link.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="hiw-item">
|
||||
<div class="dot">7</div>
|
||||
<div>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item7_title', 'Cancellation'), ENT_QUOTES, 'UTF-8')?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item7_text', 'If plans change, each specialist has their own cancellation policy.'), ENT_QUOTES, 'UTF-8')?></p>
|
||||
<h4><?php echo htmlspecialchars(t($translations, 'howitworks_item7_title', 'Cancellation'), ENT_QUOTES, 'UTF-8') ?></h4>
|
||||
<p><?php echo htmlspecialchars(t($translations, 'howitworks_item7_text', 'If plans change, each specialist has their own cancellation policy.'), ENT_QUOTES, 'UTF-8') ?></p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?php echo htmlspecialchars(t($translations, 'howitworks_goal_label', 'Our goal:'), ENT_QUOTES, 'UTF-8')?></strong>
|
||||
<?php echo htmlspecialchars(t($translations, 'howitworks_goal_text', 'Connect you with the right Russian-speaking specialist in France and make everything simple and convenient.'), ENT_QUOTES, 'UTF-8')?>
|
||||
<strong><?php echo htmlspecialchars(t($translations, 'howitworks_goal_label', 'Our goal:'), ENT_QUOTES, 'UTF-8') ?></strong>
|
||||
<?php echo htmlspecialchars(t($translations, 'howitworks_goal_text', 'Connect you with the right Russian-speaking specialist in France and make everything simple and convenient.'), ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -309,7 +309,7 @@
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?php echo $translations['copyr']?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@100..900&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Playfair+Display:wght@100800&display=swap");
|
||||
|
||||
:root {
|
||||
--red: #e03c3f;
|
||||
@@ -211,6 +212,7 @@ body {
|
||||
padding: 0 18px;
|
||||
}
|
||||
.hero-title {
|
||||
font-family: "Playfair Display", serif;
|
||||
color: #38378b;
|
||||
text-align: center;
|
||||
font-size: 48px;
|
||||
|
||||
@@ -0,0 +1,943 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@100..900&display=swap");
|
||||
|
||||
:root {
|
||||
--red: #e03c3f;
|
||||
--white: #ffffff;
|
||||
--blue: #38378b;
|
||||
--mint: #06ffa8;
|
||||
--hero: #8ca9ff; /* bleu clair fond hero (d’après maquette) */
|
||||
--header: #f1f1f1;
|
||||
--radius: 22px;
|
||||
|
||||
--c-bg: #8fa2ff; /* fond bleu/violet actuel de ton hero */
|
||||
--c-dark: #38378b; /* bleu foncé de ta charte */
|
||||
--c-white: #ffffff;
|
||||
--c-shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
.only-mobile {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 956px) {
|
||||
.only-desktop {
|
||||
display: none;
|
||||
}
|
||||
.only-mobile {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
/*Boutons page accueil du site*/
|
||||
.steps {
|
||||
width: min(800px, 92vw);
|
||||
margin: 40px auto 0;
|
||||
position: relative;
|
||||
display: grid;
|
||||
gap: 36px;
|
||||
}
|
||||
|
||||
.step {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.08));
|
||||
}
|
||||
|
||||
.step-badge {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
border-radius: 50%;
|
||||
background: var(--c-white);
|
||||
color: var(--c-dark);
|
||||
font-weight: 800;
|
||||
font-size: clamp(28px, 5vw, 56px);
|
||||
line-height: 1;
|
||||
box-shadow: var(--c-shadow);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.step-label {
|
||||
background: var(--c-white);
|
||||
color: var(--c-dark);
|
||||
font-weight: 700;
|
||||
font-size: clamp(16px, 2.6vw, 26px);
|
||||
padding: 14px 26px 14px 38px; /* pour chevauchement côté gauche */
|
||||
border-radius: 999px;
|
||||
white-space: nowrap;
|
||||
box-shadow: var(--c-shadow);
|
||||
margin-left: -30px;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* Étape 3 inversée */
|
||||
.step--reverse {
|
||||
flex-direction: row-reverse; /* inverse ordre badge et label */
|
||||
}
|
||||
|
||||
.step--reverse .step-label {
|
||||
padding: 14px 38px 14px 26px; /* espace à droite */
|
||||
margin-left: 0;
|
||||
margin-right: -30px; /* chevauchement côté droit */
|
||||
}
|
||||
/* tailles différentes pour chaque étape */
|
||||
.step:nth-child(1) .step-badge {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
font-size: clamp(28px, 5vw, 56px);
|
||||
}
|
||||
|
||||
.step:nth-child(2) .step-badge {
|
||||
width: 132px;
|
||||
height: 132px;
|
||||
font-size: clamp(32px, 5.5vw, 64px);
|
||||
}
|
||||
|
||||
.step:nth-child(3) .step-badge {
|
||||
width: 158px;
|
||||
height: 158px;
|
||||
font-size: clamp(36px, 6vw, 72px);
|
||||
}
|
||||
|
||||
/* placements (comme sur ta maquette) */
|
||||
.step--left {
|
||||
justify-self: start;
|
||||
transform: translateX(0);
|
||||
}
|
||||
.step--center {
|
||||
justify-self: center;
|
||||
transform: translateY(8px);
|
||||
padding-left: 230px;
|
||||
}
|
||||
.step--right {
|
||||
justify-self: end;
|
||||
transform: translateX(0);
|
||||
}
|
||||
/*Fin boutons rondes*/
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family:
|
||||
"Montserrat",
|
||||
system-ui,
|
||||
-apple-system,
|
||||
Segoe UI,
|
||||
Roboto,
|
||||
Arial,
|
||||
sans-serif;
|
||||
color: #111;
|
||||
/*background: var(--hero);*/
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto; /* header, contenu, footer */
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.site-header {
|
||||
background: var(--header);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.site-header .container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 10px 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/* ==== LOGO: mobile vs desktop (béton) ==== */
|
||||
.brand {
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 0; /* évite petits décalages baseline */
|
||||
}
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px; /* distance logo ↔ langue */
|
||||
}
|
||||
.brand .logo-mobile,
|
||||
.brand .logo-desktop {
|
||||
display: none !important; /* on cache tout par défaut */
|
||||
height: 40px; /* taille unique (tu ajustes) */
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Mobile: logo_u */
|
||||
@media (max-width: 767.98px) {
|
||||
.brand .logo-mobile {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop: logo.png */
|
||||
@media (min-width: 768px) {
|
||||
.brand .logo-desktop {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Actions header */
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.icon-btn {
|
||||
border: none;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* HERO */
|
||||
.hero {
|
||||
padding: 0 0 56px;
|
||||
background: var(--hero);
|
||||
}
|
||||
.hero .container {
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 0 18px;
|
||||
}
|
||||
.hero-title {
|
||||
color: #38378b;
|
||||
text-align: center;
|
||||
font-size: 48px;
|
||||
line-height: 1.16;
|
||||
font-weight: 800;
|
||||
margin: 5px 0 26px;
|
||||
}
|
||||
|
||||
/* Bouton LOGIN */
|
||||
.btn-login {
|
||||
background: var(--red);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: 8px 14px;
|
||||
border-radius: 999px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.18);
|
||||
/*font-size: clamp(12px, 2vw, 16px);*/
|
||||
}
|
||||
|
||||
/* grille 3 au-dessus + 1 en dessous */
|
||||
|
||||
/* style des blocs ovales */
|
||||
|
||||
.hero .row {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
margin: 15px 0;
|
||||
flex-wrap: wrap; /* au cas où ; reste cohérent */
|
||||
}
|
||||
|
||||
.chip {
|
||||
appearance: none;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
color: #000000;
|
||||
width: 230px; /* largeur fixe */
|
||||
text-align: center; /* texte centré */
|
||||
padding: 12px 0; /* hauteur uniforme */
|
||||
border-radius: 15px; /* ovale */
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.15);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Footer plus large (haut) et gris, toujours en bas */
|
||||
footer {
|
||||
background: var(--header);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
||||
padding: 22px 20px; /* plus haut qu’avant */
|
||||
}
|
||||
footer p {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
color: #222;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/*===================================================================================================================*/
|
||||
|
||||
/*La partie affichage pour la page aprés la recherche*/
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 18px;
|
||||
}
|
||||
|
||||
/* Liste : espace entre blocs */
|
||||
.pro-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 40px; /* augmente l’écart vertical */
|
||||
padding: 20px 0 40px;
|
||||
}
|
||||
|
||||
/* Carte = 4 colonnes : photo | infos | vidéo | bouton */
|
||||
.pro-card {
|
||||
background: #fff;
|
||||
border-radius: 28px;
|
||||
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.18);
|
||||
display: grid;
|
||||
/* NE PAS forcer start ici */
|
||||
align-items: stretch; /* <— important */
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
grid-template-columns: 260px 1.5fr 240px 180px;
|
||||
grid-template-areas: "photo info video cta";
|
||||
}
|
||||
|
||||
/* 1) Photo portrait, non déformée (recadrage OK) */
|
||||
.pro-photo {
|
||||
grid-area: photo;
|
||||
}
|
||||
.pro-photo img {
|
||||
width: 100%;
|
||||
aspect-ratio: 3/4; /* portrait */
|
||||
object-fit: cover; /* pas de déformation */
|
||||
display: block;
|
||||
border-radius: 22px;
|
||||
}
|
||||
|
||||
/* 2) Infos */
|
||||
.pro-info {
|
||||
grid-area: info;
|
||||
padding: 0 6px;
|
||||
color: #1b1b1b;
|
||||
}
|
||||
.pro-name {
|
||||
margin: 0 0 8px;
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.pro-spec {
|
||||
color: #38378b;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.pro-desc {
|
||||
color: #3f3f3f;
|
||||
line-height: 1.45;
|
||||
font-size: 1.05rem; /* augmente légèrement la taille */
|
||||
max-width: 95%; /* laisse plus d’espace dans la colonne */
|
||||
}
|
||||
.pro-info .favori {
|
||||
top: 10px;
|
||||
right: 10px; /* passe à left:10px si tu le veux à gauche */
|
||||
z-index: 2;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
filter: drop-shadow(0 2px 6px rgba(6, 6, 6, 0.25));
|
||||
transition:
|
||||
transform 0.15s ease,
|
||||
opacity 0.15s ease;
|
||||
}
|
||||
.pro-info .favori:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
.pro-info .favori.ajoute {
|
||||
color: rgb(12, 12, 11);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
/* 3) Vidéo (vignette 16:9) */
|
||||
/* même gabarit pour lien vidéo ET placeholder */
|
||||
.pro-video,
|
||||
.pro-video.placeholder {
|
||||
position: relative;
|
||||
display: block;
|
||||
aspect-ratio: 4 / 3; /* <- ton format souhaité */
|
||||
max-height: 180px;
|
||||
border-radius: 18px;
|
||||
overflow: hidden;
|
||||
background: #000; /* évite les bordures blanches */
|
||||
}
|
||||
|
||||
/* l'image occupe tout l'espace du cadre */
|
||||
.pro-video img,
|
||||
.pro-video.placeholder img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* optionnel: largeur de la colonne vidéo */
|
||||
.pro-video-col {
|
||||
display: flex;
|
||||
align-items: center; /* centre verticalement dans la colonne */
|
||||
justify-content: center;
|
||||
width: clamp(240px, 32vw, 200px);
|
||||
}
|
||||
|
||||
/* 4) Bouton dans sa colonne, centré verticalement et aligné à droite */
|
||||
.pro-cta-col {
|
||||
grid-area: cta;
|
||||
display: flex;
|
||||
align-items: center; /* centre verticalement */
|
||||
justify-content: center; /* centre horizontalement */
|
||||
}
|
||||
|
||||
.pro-cta {
|
||||
background: #e03c3f;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
padding: 10px 18px;
|
||||
border-radius: 999px;
|
||||
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.18);
|
||||
white-space: nowrap;
|
||||
/*font-size: 0.95rem;*/
|
||||
}
|
||||
|
||||
/* Langue choix*/
|
||||
/* Sélecteur de langue dans le header */
|
||||
.lang-switch {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
height: 42px;
|
||||
background: #fff;
|
||||
padding: 6px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.lang-btn {
|
||||
display: inline-block;
|
||||
padding: 4px 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
color: #38378b; /* bleu foncé */
|
||||
border-radius: 14px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.lang-btn:hover {
|
||||
background: rgba(56, 55, 139, 0.08);
|
||||
}
|
||||
|
||||
.lang-btn.active {
|
||||
background: #38378b; /* bleu foncé */
|
||||
color: #fff;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Compact */
|
||||
.pro-card--sm {
|
||||
--pro-card-pad: 12px;
|
||||
--pro-card-gap: 10px;
|
||||
--pro-avatar: 72px;
|
||||
--pro-title: 16px;
|
||||
--pro-lines: 2;
|
||||
}
|
||||
|
||||
/* Large */
|
||||
.pro-card--lg {
|
||||
--pro-card-pad: 22px;
|
||||
--pro-card-gap: 18px;
|
||||
--pro-avatar: 100px;
|
||||
--pro-title: 20px;
|
||||
--pro-lines: 4;
|
||||
}
|
||||
|
||||
.results-title,
|
||||
.results-meta,
|
||||
.result-count {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-logo {
|
||||
--bs-btn-bg: #38378b;
|
||||
--bs-btn-border-color: #38378b;
|
||||
--bs-btn-hover-bg: #2f2e77;
|
||||
--bs-btn-hover-border-color: #2f2e77;
|
||||
--bs-btn-active-bg: #24235e;
|
||||
--bs-btn-active-border-color: #24235e;
|
||||
--bs-btn-color: #fff; /* blanc par défaut */
|
||||
--bs-btn-focus-shadow-rgb: 56, 55, 139; /* halo focus */
|
||||
}
|
||||
|
||||
/* On force la couleur du texte à blanc dans tous les états */
|
||||
.btn-logo,
|
||||
.btn-logo:hover,
|
||||
.btn-logo:active,
|
||||
.btn-logo:focus,
|
||||
.btn-logo:focus-visible {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Menu compact, largeur auto comme dans ta maquette */
|
||||
.help-menu {
|
||||
min-width: auto; /* override Bootstrap */
|
||||
width: max-content; /* s’adapte au contenu */
|
||||
max-width: 92vw; /* borne mobile */
|
||||
border-radius: 12px;
|
||||
padding: 8px;
|
||||
}
|
||||
.help-menu .dropdown-item {
|
||||
padding: 10px 14px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.help-menu .dropdown-item + .dropdown-item {
|
||||
margin-top: 6px;
|
||||
} /* petits espacements */
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.help-menu {
|
||||
max-width: 360px;
|
||||
} /* borne desktop */
|
||||
}
|
||||
|
||||
/* Taille tactile du bouton “?” */
|
||||
.question-btn {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Menu plus étroit (recommandé) */
|
||||
.offcanvas-slim {
|
||||
--bs-offcanvas-width: clamp(240px, 80vw, 320px);
|
||||
}
|
||||
|
||||
/* Option: largeur calée au titre (plus “compacte”) */
|
||||
/* .offcanvas-slim{ --bs-offcanvas-width: fit-content; max-width: min(90vw, 360px); } */
|
||||
|
||||
/* Fallback minimal sans Bootstrap */
|
||||
.d-none {
|
||||
display: none !important;
|
||||
}
|
||||
.d-sm-inline {
|
||||
display: none !important;
|
||||
}
|
||||
.d-sm-none {
|
||||
display: inline !important;
|
||||
}
|
||||
.text-nowrap {
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.d-sm-inline {
|
||||
display: inline !important;
|
||||
}
|
||||
.d-sm-none {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==== VISUEL COMMUN POUR TOUS LES MENUS ==== */
|
||||
.menu-panel {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
|
||||
min-width: 230px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* Items menu principal (li custom OU .dropdown-item Bootstrap) */
|
||||
.menu-panel > li,
|
||||
.menu-panel .dropdown-item {
|
||||
padding: 12px 18px;
|
||||
font-size: 16px;
|
||||
line-height: 1.25;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.menu-panel > li + li,
|
||||
.menu-panel .dropdown-item + .dropdown-item {
|
||||
border-top: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
.menu-panel > li:hover,
|
||||
.menu-panel .dropdown-item:hover {
|
||||
background: #f8f9fa; /* juste fond gris clair */
|
||||
}
|
||||
|
||||
.menu-panel a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ==== MENU “BURGER” CUSTOM ==== */
|
||||
.menu-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dropdown-menu-custom {
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
right: 0;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
display: none; /* fermé par défaut */
|
||||
z-index: 1100;
|
||||
}
|
||||
|
||||
.dropdown-menu-custom.is-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Sous-menu */
|
||||
.has-submenu .submenu-toggle {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
background: none;
|
||||
border: 0;
|
||||
padding: 0.55rem 1rem;
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.submenu {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0.5rem 0;
|
||||
}
|
||||
|
||||
.submenu > li {
|
||||
padding: 0.4rem 1rem 0.4rem 1.5rem;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.submenu > li:hover {
|
||||
background: #fff; /* juste fond gris clair */
|
||||
}
|
||||
|
||||
.submenu[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ==== MENU “?” BOOTSTRAP ==== */
|
||||
.dropdown-menu.menu-panel {
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
|
||||
min-width: 230px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* Sécurité : que rien ne coupe les menus */
|
||||
.site-header,
|
||||
.header-actions,
|
||||
.menu-wrap,
|
||||
.dropdown {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* Bouton avatar (menu principal) */
|
||||
#btnMenu {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent; /* enlève flash bleu sur mobile */
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/* Supprime le halo/cadre bleu par défaut */
|
||||
#btnMenu:focus,
|
||||
#btnMenu:active {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Si tu veux garder une indication focus clavier accessible */
|
||||
#btnMenu:focus-visible {
|
||||
outline: 2px solid var(--color-blue); /* ou une couleur douce */
|
||||
outline-offset: 3px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.footer-top-links {
|
||||
color: #38378b;
|
||||
font-weight: 600;
|
||||
}
|
||||
.footer-top-links a {
|
||||
color: inherit; /* hérite du bleu foncé */
|
||||
}
|
||||
|
||||
/* ===== Personnalisation bandeau cookies (CookieConsent v3) ===== */
|
||||
#cc-main {
|
||||
--cc-font-family: "Montserrat", sans-serif;
|
||||
/* Couleurs de texte */
|
||||
--cc-primary-color: #38378b; /* titres/links -> bleu foncé */
|
||||
--cc-secondary-color: #38378b; /* paragraphe du bandeau */
|
||||
|
||||
/* Bouton principal (Accepter tout) -> rouge arrondi */
|
||||
--cc-btn-border-radius: 22px;
|
||||
--cc-btn-primary-bg: #e03c3f;
|
||||
--cc-btn-primary-color: #ffffff;
|
||||
--cc-btn-primary-border-color: #e03c3f;
|
||||
--cc-btn-primary-hover-bg: #c92f33; /* rouge un peu plus foncé */
|
||||
--cc-btn-primary-hover-color: #ffffff;
|
||||
--cc-btn-primary-hover-border-color: #c92f33;
|
||||
|
||||
/* Boutons secondaires (Refuser / Paramétrer) -> fond blanc, bord gris, arrondi */
|
||||
--cc-btn-secondary-bg: #ffffff;
|
||||
--cc-btn-secondary-color: #38378b;
|
||||
--cc-btn-secondary-border-color: #d9dee3;
|
||||
--cc-btn-secondary-hover-bg: #f4f6f8;
|
||||
--cc-btn-secondary-hover-color: #38378b;
|
||||
--cc-btn-secondary-hover-border-color: #c9d0d6;
|
||||
|
||||
/* Séparateur & fond pieds/bords pour un rendu plus clean */
|
||||
--cc-separator-border-color: #eef2f5;
|
||||
--cc-footer-bg: #ffffff;
|
||||
--cc-footer-color: #38378b;
|
||||
|
||||
/* Optionnel: arrondir la carte elle-même */
|
||||
--cc-modal-border-radius: 22px;
|
||||
}
|
||||
|
||||
/* Si tu veux forcer l’arrondi aussi quand des classes sont injectées */
|
||||
#cc-main .cm__btn,
|
||||
#cc-main .pm__btn {
|
||||
border-radius: 22px;
|
||||
}
|
||||
|
||||
/*===================================================================================================================*/
|
||||
/* --- Container modal --- */
|
||||
.vmodal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: none;
|
||||
z-index: 99999;
|
||||
}
|
||||
.vmodal[aria-hidden="false"] {
|
||||
display: block;
|
||||
}
|
||||
.vmodal__backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
/* --- Boîte --- */
|
||||
.vmodal__dialog {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
max-width: 1000px;
|
||||
width: 92%;
|
||||
margin: 40px auto;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
|
||||
overflow: hidden; /* pour arrondis propres */
|
||||
}
|
||||
|
||||
/* --- Header “Bootstrap-like” --- */
|
||||
.vmodal__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.85rem 1rem;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
background: #fff;
|
||||
}
|
||||
.vmodal__title {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
/* --- Close visible (rond blanc) --- */
|
||||
.vmodal__close {
|
||||
border: 0;
|
||||
background: #fff;
|
||||
color: #111;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 999px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
.vmodal__close:hover {
|
||||
filter: brightness(0.95);
|
||||
}
|
||||
|
||||
/* --- Body + ratio vidéo --- */
|
||||
.vmodal__body {
|
||||
padding: 1rem;
|
||||
}
|
||||
.vmodal__ratio {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 16/9;
|
||||
overflow: hidden;
|
||||
border-radius: 12px;
|
||||
background: #000;
|
||||
}
|
||||
.vmodal__ratio iframe {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* --- Footer --- */
|
||||
.vmodal__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
padding: 0.85rem 1rem;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
background: #fff;
|
||||
}
|
||||
.btn.btn-secondary-like {
|
||||
appearance: none;
|
||||
border: 1px solid #ced4da;
|
||||
background: #f8f9fa;
|
||||
color: #212529;
|
||||
padding: 0.5rem 0.9rem;
|
||||
border-radius: 0.35rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn.btn-secondary-like:hover {
|
||||
background: #e9ecef;
|
||||
}
|
||||
.no-results {
|
||||
text-align: center; /* centre le texte */
|
||||
color: #fff; /* texte en blanc */
|
||||
}
|
||||
/* --- Mobile --- */
|
||||
@media (max-width: 575.98px) {
|
||||
.vmodal__dialog {
|
||||
margin: 16px auto;
|
||||
width: 96%;
|
||||
}
|
||||
.vmodal__title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.pager {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin: 22px 0;
|
||||
}
|
||||
.pager a {
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
.pager-arrow {
|
||||
padding: 10px 18px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #e0e3eb;
|
||||
background: #fff;
|
||||
color: #38378b;
|
||||
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.06);
|
||||
transition:
|
||||
background 0.2s,
|
||||
transform 0.1s,
|
||||
opacity 0.2s;
|
||||
}
|
||||
.pager-arrow:hover {
|
||||
background: #f8f9ff;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.pager-arrow.is-disabled {
|
||||
opacity: 0.4;
|
||||
pointer-events: none;
|
||||
}
|
||||
.pager-page {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #e0e3eb;
|
||||
background: #fff;
|
||||
color: #38378b;
|
||||
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.06);
|
||||
transition:
|
||||
background 0.2s,
|
||||
transform 0.1s,
|
||||
color 0.2s,
|
||||
border-color 0.2s;
|
||||
}
|
||||
.pager-page:hover {
|
||||
background: #f8f9ff;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.pager-page.is-active {
|
||||
background: #e03c3f;
|
||||
color: #fff;
|
||||
border-color: #e03c3f;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.menu-item-form {
|
||||
padding: 0 !important;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.menu-logout-form {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.menu-logout-btn {
|
||||
all: unset;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
cursor: pointer;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.menu-logout-btn:hover {
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
.menu-logout-btn:focus-visible {
|
||||
outline: 2px solid #94a3b8;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
+10
-13
@@ -291,36 +291,32 @@
|
||||
margin-top: 24px;
|
||||
padding: 28px 22px;
|
||||
border-radius: 12px;
|
||||
|
||||
background: #8ca9ff;
|
||||
box-shadow: 0 20px 40px rgba(127, 91, 255, 0.2);
|
||||
|
||||
color: #fff;
|
||||
|
||||
/* ⬇️ IMPORTANT */
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto; /* gauche | milieu | droite */
|
||||
align-items: center;
|
||||
column-gap: 22px;
|
||||
|
||||
text-align: left;
|
||||
/* 1. Force l'alignement horizontal global des colonnes au centre */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Titre */
|
||||
.spec-cta-wrap h3 {
|
||||
margin: 0;
|
||||
font-size: 34px; /* pour se rapprocher de la capture 2 */
|
||||
font-weight: 700;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
white-space: nowrap; /* optionnel: évite retour ligne */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Paragraphe */
|
||||
.spec-cta-wrap p {
|
||||
margin: 0;
|
||||
margin: 0 auto; /* 2. "auto" à gauche et à droite centre le bloc qui a un max-width */
|
||||
font-size: 18px;
|
||||
opacity: 0.95;
|
||||
line-height: 1.35;
|
||||
max-width: 520px; /* pour un look “milieu” */
|
||||
max-width: 520px;
|
||||
}
|
||||
|
||||
/* Bouton blanc */
|
||||
@@ -488,7 +484,8 @@
|
||||
}
|
||||
|
||||
.spec-cta-wrap h3 {
|
||||
font-size: 26px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,507 @@
|
||||
/* =========================================================
|
||||
1) Liens / Chips
|
||||
========================================================= */
|
||||
.chip-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
2) Grand panneau blanc
|
||||
========================================================= */
|
||||
.home-panel {
|
||||
max-width: 850px;
|
||||
margin: 22px auto 0;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
border: 1px solid rgba(255, 255, 255, 0.45);
|
||||
border-radius: 22px;
|
||||
/*box-shadow: 0 10px 26px rgba(0, 0, 0, 0.14);*/
|
||||
overflow: hidden;
|
||||
}
|
||||
.home-panel__inner {
|
||||
padding: 18px 16px;
|
||||
}
|
||||
.home-panel__divider {
|
||||
height: 1px;
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
3) Checklist
|
||||
========================================================= */
|
||||
.home-checklist {
|
||||
padding: 14px 14px 10px;
|
||||
}
|
||||
.home-checklist ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.home-checklist li {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: flex-start;
|
||||
color: #1b1b1b;
|
||||
}
|
||||
.home-check {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 999px;
|
||||
background: rgba(6, 255, 168, 0.18);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.home-check svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
4) Titres
|
||||
========================================================= */
|
||||
.home-h2 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
color: #1b1b1b;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
5) Liste praticiens
|
||||
========================================================= */
|
||||
.hp-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* --- Carte --- */
|
||||
.hp-card {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.08);
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* --- Ligne 1 : avatar | texte | rating --- */
|
||||
.hp-row1 {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.hp-avatar {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 14px;
|
||||
object-fit: cover;
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.hp-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.hp-name {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
color: #111;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.hp-spec {
|
||||
margin-top: 2px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* --- Rating (étoiles base + fill) --- */
|
||||
.hp-rating {
|
||||
text-align: right;
|
||||
min-width: 110px;
|
||||
}
|
||||
|
||||
.hp-stars {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.hp-stars .stars-base {
|
||||
color: #ddd;
|
||||
}
|
||||
.hp-stars .stars-fill {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
color: #f5b301;
|
||||
}
|
||||
|
||||
.hp-note {
|
||||
margin-top: 2px;
|
||||
font-size: 0.85rem;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
/* --- Ligne 2 : Online (gauche) | bouton (droite) --- */
|
||||
.hp-row2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
padding-left: 68px; /* aligné sous le texte (56 avatar + gap) */
|
||||
}
|
||||
|
||||
.hp-online {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #111;
|
||||
opacity: 0.9;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* --- Bouton --- */
|
||||
.hp-btn {
|
||||
background: var(--red, #e03c3f);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
border-radius: 999px;
|
||||
padding: 10px 14px;
|
||||
min-width: 110px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.16);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
6) Mini steps
|
||||
========================================================= */
|
||||
.hp-steps {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.08);
|
||||
padding: 12px 14px;
|
||||
}
|
||||
|
||||
/* --- Nouveau : entête (sobre) --- */
|
||||
.hp-steps__head {
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.hp-steps__title {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
color: #111;
|
||||
}
|
||||
.hp-steps__sub {
|
||||
margin: 6px 0 0;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* --- Nouveau : grille steps propre (sans <br>) --- */
|
||||
.hp-steps__grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 10px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.hp-steps__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.hp-steps__arr {
|
||||
color: #6b7280;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
7) Articles
|
||||
========================================================= */
|
||||
.hp-articles {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
.ha {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
background: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
color: #111;
|
||||
}
|
||||
.ha-img {
|
||||
height: 92px;
|
||||
background: #e9edf8;
|
||||
}
|
||||
.ha-body {
|
||||
padding: 10px 12px 12px;
|
||||
}
|
||||
.ha-title {
|
||||
margin: 0 0 6px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.ha-sub {
|
||||
margin: 0;
|
||||
font-size: 12.5px;
|
||||
font-weight: 400;
|
||||
color: #6b7280;
|
||||
}
|
||||
.hp-all {
|
||||
text-align: center;
|
||||
padding-top: 10px;
|
||||
}
|
||||
.hp-all a {
|
||||
font-weight: 600;
|
||||
color: #1f3bb3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.spec-cta-wrap {
|
||||
margin-top: 24px;
|
||||
padding: 28px 22px;
|
||||
border-radius: 12px;
|
||||
|
||||
background: #8ca9ff;
|
||||
box-shadow: 0 20px 40px rgba(127, 91, 255, 0.2);
|
||||
|
||||
color: #fff;
|
||||
|
||||
/* ⬇️ IMPORTANT */
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto; /* gauche | milieu | droite */
|
||||
align-items: center;
|
||||
column-gap: 22px;
|
||||
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Titre */
|
||||
.spec-cta-wrap h3 {
|
||||
margin: 0;
|
||||
font-size: 34px; /* pour se rapprocher de la capture 2 */
|
||||
font-weight: 700;
|
||||
line-height: 1.1;
|
||||
white-space: nowrap; /* optionnel: évite retour ligne */
|
||||
}
|
||||
|
||||
.spec-cta-wrap p {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
opacity: 0.95;
|
||||
line-height: 1.35;
|
||||
max-width: 520px; /* pour un look “milieu” */
|
||||
}
|
||||
|
||||
/* Bouton blanc */
|
||||
.spec-cta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
|
||||
padding: 12px 24px;
|
||||
border-radius: 999px;
|
||||
|
||||
background: #fff;
|
||||
color: #8ca9ff;
|
||||
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
|
||||
text-decoration: none;
|
||||
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.12);
|
||||
|
||||
transition:
|
||||
transform 0.18s ease,
|
||||
box-shadow 0.18s ease;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.spec-cta:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 22px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
/* Active */
|
||||
.spec-cta:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
/* Barre style "carte" */
|
||||
.searchbar {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
padding: 10px 14px;
|
||||
max-width: 860px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
margin-left: 6px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.input-wrap {
|
||||
position: relative;
|
||||
flex: 1 1 0;
|
||||
min-width: 0; /* IMPORTANT: évite débordements */
|
||||
}
|
||||
|
||||
/* Champs “plats” (comme sur ta capture) */
|
||||
.searchbar input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
font-size: 14px;
|
||||
padding: 10px 8px;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.searchbar input::placeholder {
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
/* séparateur */
|
||||
.divider {
|
||||
width: 1px;
|
||||
height: 34px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Bouton intégré à droite */
|
||||
.btn-find--inbar {
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: var(--red);
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.16);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-find--inbar:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-find--inbar:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Suggestions dropdown */
|
||||
.suggest {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
list-style: none;
|
||||
margin: 6px 0 0;
|
||||
padding: 6px 0;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.14);
|
||||
max-height: 260px;
|
||||
overflow: auto;
|
||||
z-index: 20;
|
||||
}
|
||||
.suggest li {
|
||||
padding: 10px 12px;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
}
|
||||
.suggest li:hover {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
8) Mobile
|
||||
========================================================= */
|
||||
@media (max-width: 720px) {
|
||||
.hp-btn {
|
||||
min-width: 112px;
|
||||
padding: 9px 12px;
|
||||
}
|
||||
.hp-row2 {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.ha-img {
|
||||
height: 90px;
|
||||
}
|
||||
.hp-articles {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.hp-steps__title {
|
||||
font-size: 17px;
|
||||
}
|
||||
.hp-steps__sub {
|
||||
font-size: 12.5px;
|
||||
}
|
||||
.hp-steps__item {
|
||||
font-size: 13.5px;
|
||||
}
|
||||
.spec-cta-wrap {
|
||||
grid-template-columns: 1fr;
|
||||
row-gap: 12px;
|
||||
text-align: center;
|
||||
justify-items: center;
|
||||
padding: 22px 18px;
|
||||
}
|
||||
|
||||
.spec-cta-wrap h3 {
|
||||
font-size: 26px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.spec-cta-wrap p {
|
||||
font-size: 15px;
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.spec-cta {
|
||||
width: 50%;
|
||||
max-width: 340px;
|
||||
}
|
||||
.hero {
|
||||
background: #f3f4f8;
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -4,26 +4,26 @@ return [
|
||||
'ru' => [
|
||||
'avocats' => 'адвокат',
|
||||
'consultants' => 'консультант',
|
||||
'vrachi' => 'врач',
|
||||
//'vrachi' => 'врач', // clé existante "vrachi" côté traductions
|
||||
'psychologues' => 'психолог',
|
||||
'repetitori' => 'преподаватель',
|
||||
'finance' => 'бухгалтер', // ajuste si besoin
|
||||
//'repetitori' => 'преподаватель',
|
||||
//'finance' => 'бухгалтер', // ajuste si besoin
|
||||
'perevod' => 'переводчик',
|
||||
'notarius' => 'нотариус',
|
||||
'gid' => 'гид',
|
||||
//'notarius' => 'нотариус',
|
||||
//'gid' => 'гид',
|
||||
'rieltori' => 'риелтор',
|
||||
|
||||
],
|
||||
'fr' => [
|
||||
'avocats' => 'адвокат',
|
||||
'consultants' => 'консультант',
|
||||
'vrachi' => 'врач', // clé existante "vrachi" côté traductions
|
||||
//'vrachi' => 'врач', // clé existante "vrachi" côté traductions
|
||||
'psychologues' => 'психолог',
|
||||
'repetitori' => 'преподаватель', // ou "Répetiteur" selon ta BDD
|
||||
'finance' => 'бухгалтер', // ajuste si besoin
|
||||
//'repetitori' => 'преподаватель', // ou "Répetiteur" selon ta BDD
|
||||
//'finance' => 'бухгалтер', // ajuste si besoin
|
||||
'perevod' => 'переводчик',
|
||||
'notarius' => 'нотариус',
|
||||
'gid' => 'гид',
|
||||
//'notarius' => 'нотариус',
|
||||
//'gid' => 'гид',
|
||||
'rieltori' => 'риелтор',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
// Map des clés de traduction -> valeur canonique (singulier) pour la BDD
|
||||
return [
|
||||
'ru' => [
|
||||
'avocats' => 'адвокат',
|
||||
'consultants' => 'консультант',
|
||||
'vrachi' => 'врач',
|
||||
'psychologues' => 'психолог',
|
||||
'repetitori' => 'преподаватель',
|
||||
'finance' => 'бухгалтер', // ajuste si besoin
|
||||
'perevod' => 'переводчик',
|
||||
'notarius' => 'нотариус',
|
||||
'gid' => 'гид',
|
||||
'rieltori' => 'риелтор',
|
||||
|
||||
],
|
||||
'fr' => [
|
||||
'avocats' => 'адвокат',
|
||||
'consultants' => 'консультант',
|
||||
'vrachi' => 'врач', // clé existante "vrachi" côté traductions
|
||||
'psychologues' => 'психолог',
|
||||
'repetitori' => 'преподаватель', // ou "Répetiteur" selon ta BDD
|
||||
'finance' => 'бухгалтер', // ajuste si besoin
|
||||
'perevod' => 'переводчик',
|
||||
'notarius' => 'нотариус',
|
||||
'gid' => 'гид',
|
||||
'rieltori' => 'риелтор',
|
||||
],
|
||||
];
|
||||
+15
-13
@@ -1,16 +1,18 @@
|
||||
<?php
|
||||
// Charge les scripts de tracking uniquement pour des pages HTML vues en GET.
|
||||
// → Pas d’injection sur API/AJAX/assets/callbacks.
|
||||
if (PHP_SAPI === 'cli') return;
|
||||
if (PHP_SAPI === 'cli') {
|
||||
return;
|
||||
}
|
||||
|
||||
$uri = $_SERVER['REQUEST_URI'] ?? '';
|
||||
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
||||
$xrw = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
|
||||
$uri = $_SERVER['REQUEST_URI'] ?? '';
|
||||
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
||||
$xrw = $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '';
|
||||
|
||||
$isGet = strcasecmp($method, 'GET') === 0;
|
||||
$wantsHtml = (stripos($accept, 'text/html') !== false) || ($accept === '');
|
||||
$wantsJson = stripos($accept, 'application/json') !== false;
|
||||
$isGet = strcasecmp($method, 'GET') === 0;
|
||||
$wantsHtml = (stripos($accept, 'text/html') !== false) || ($accept === '');
|
||||
$wantsJson = stripos($accept, 'application/json') !== false;
|
||||
|
||||
$isAjax = strcasecmp($xrw, 'XMLHttpRequest') === 0;
|
||||
$isApi = preg_match('~/(api/|messages/api/|webhook|callback|notify)~i', $uri);
|
||||
@@ -18,9 +20,9 @@ $isAsset = preg_match('~\.(css|js|map|png|jpe?g|gif|svg|webp|ico|json|xml|txt|p
|
||||
$isMatomo = stripos($uri, '/matomo/') !== false;
|
||||
$isRdv = preg_match('~/(valider_rdv\.php|confirmer_rdv\.php|rdv/)~i', $uri);
|
||||
|
||||
if ($isGet && $wantsHtml && !$wantsJson && !$isAjax && !$isApi && !$isAsset && !$isMatomo && !$isRdv) {
|
||||
// 100% externe (pas d’inline) → compatible CSP 'self' + domaines autorisés
|
||||
echo '<script src="/js/tracking.js" defer></script>';
|
||||
// Pixel noscript Matomo (ok même sans JS)
|
||||
echo '<noscript><p><img src="https://staging.uslugi.fr/matomo/matomo.php?idsite=1&rec=1" style="border:0" alt=""></p></noscript>';
|
||||
if ($isGet && $wantsHtml && ! $wantsJson && ! $isAjax && ! $isApi && ! $isAsset && ! $isMatomo && ! $isRdv) {
|
||||
// 100% externe (pas d’inline) → compatible CSP 'self' + domaines autorisés
|
||||
echo '<script src="/js/tracking.js" defer></script>';
|
||||
// Pixel noscript Matomo (ok même sans JS)
|
||||
//echo '<noscript><p><img src="https://staging.uslugi.fr/matomo/matomo.php?idsite=1&rec=1" style="border:0" alt=""></p></noscript>';
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('log_errors', '1');
|
||||
ini_set('error_log', __DIR__ . '/php-debug.log');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
register_shutdown_function(function () {
|
||||
$e = error_get_last();
|
||||
file_put_contents(__DIR__ . '/php-debug.log',
|
||||
"SHUTDOWN: " . print_r($e, true) . "\n",
|
||||
FILE_APPEND
|
||||
);
|
||||
});
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
|
||||
require_once __DIR__ . '/includes/search_helpers.php';
|
||||
@@ -250,6 +239,12 @@ else: ?>
|
||||
<button id="pwaIosClose" class="pwa-ios-close" type="button">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Banniere En haut de la page index✅ Fin PWA -->
|
||||
<a href="/registration.php">
|
||||
<div class="spec-cta-wrap">
|
||||
<h3><?php echo $translations['choix_pro_titre_home_banner'] ?? '' ?></h3>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<br>
|
||||
<h1 class="hero-title">
|
||||
@@ -264,9 +259,9 @@ else: ?>
|
||||
<center><h5><?php echo($translations['sous_titre_home'] ?? '') ?></h5></center>
|
||||
<br>
|
||||
<?php
|
||||
$chipKeysRow1 = ['avocats', 'notarius', 'rieltori'];
|
||||
$chipKeysRow2 = ['vrachi', 'psychologues', 'consultants'];
|
||||
$chipKeysRow3 = ['perevod', 'repetitori', 'drugie'];
|
||||
$chipKeysRow1 = ['avocats', 'rieltori', 'psychologues'];
|
||||
$chipKeysRow2 = ['consultants', 'perevod', 'drugie'];
|
||||
//$chipKeysRow3 = ['perevod', 'repetitori', 'drugie'];
|
||||
|
||||
$renderChipLinks = function (array $keys) use ($translations) {
|
||||
foreach ($keys as $k) {
|
||||
@@ -288,7 +283,7 @@ else: ?>
|
||||
</h2>
|
||||
<div class="row"><?php $renderChipLinks($chipKeysRow1); ?></div>
|
||||
<div class="row"><?php $renderChipLinks($chipKeysRow2); ?></div>
|
||||
<div class="row"><?php $renderChipLinks($chipKeysRow3); ?></div>
|
||||
<div class="row"><?php //$renderChipLinks($chipKeysRow3); ?></div>
|
||||
|
||||
<br>
|
||||
<h2 class="visually-hidden">
|
||||
@@ -485,14 +480,15 @@ else: ?>
|
||||
<button class="hp-btn btn-find--inbar" type="submit">
|
||||
<?php echo h($translations['naiti'] ?? '') ?>
|
||||
</button>
|
||||
</form><br>
|
||||
</form>
|
||||
<br>
|
||||
<a href="/form_index_recomender.php">
|
||||
<div class="spec-cta-wrap">
|
||||
<h3><?php echo h($translations['choix_pro_titre_home'] ?? '') ?></h3>
|
||||
<p><!--<?php echo h($translations['choix_pro_texte_court'] ?? '') ?>--></p>
|
||||
<a class="spec-cta" href="/registration.php">
|
||||
<span class="spec-cta__label"><?php echo h($translations['titre_spec'] ?? '') ?></span>
|
||||
</a>
|
||||
<h3><?php echo $translations['choix_pro_titre_home'] ?? '' ?></h3>
|
||||
<!--<p><?php echo h($translations['choix_pro_texte_court'] ?? '') ?></p>
|
||||
<span class="spec-cta__label"><?php echo h($translations['titre_spec'] ?? '') ?></span>-->
|
||||
</div>
|
||||
</a>
|
||||
<br>
|
||||
<!--<div class="hp-all">
|
||||
<a href="/result_search.php">
|
||||
|
||||
+521
@@ -0,0 +1,521 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
require_once APP_HTDOCS . '/includes/avatar_initiales.php';
|
||||
require_once __DIR__ . '/includes/search_helpers.php';
|
||||
require_once __DIR__ . '/traitement_form_index.php';
|
||||
|
||||
$SPEC_CANON = require __DIR__ . '/includes/spec_map.php';
|
||||
$canon = $SPEC_CANON[$lang] ?? [];
|
||||
|
||||
/* =========================
|
||||
AJAX: suggestions
|
||||
========================= */
|
||||
if (isset($_GET['ajax']) && $_GET['ajax'] === 'suggest') {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
$field = (string) ($_GET['field'] ?? '');
|
||||
$q = trim((string) ($_GET['q'] ?? ''));
|
||||
if (! in_array($field, ['specialite', 'ville'], true)) {echo json_encode([]);exit;}
|
||||
|
||||
require_once __DIR__ . '/includes/search_helpers.php';
|
||||
|
||||
$params = [];
|
||||
$sql = '';
|
||||
|
||||
if ($field === 'ville') {
|
||||
$sql = "SELECT DISTINCT ville AS val
|
||||
FROM praticien
|
||||
WHERE ville IS NOT NULL AND ville <> ''";
|
||||
|
||||
if ($q !== '') {
|
||||
$cands = city_query_candidates($q);
|
||||
$cands[] = mb_strtolower($q, 'UTF-8');
|
||||
$cands = array_values(array_unique($cands));
|
||||
|
||||
$ors = [];
|
||||
foreach ($cands as $i => $cand) {
|
||||
$ors[] = "LOWER(ville) LIKE :q$i";
|
||||
$params[":q$i"] = $cand . '%';
|
||||
}
|
||||
if ($ors) {
|
||||
$sql .= " AND (" . implode(' OR ', $ors) . ")";
|
||||
}
|
||||
|
||||
}
|
||||
$sql .= " ORDER BY val ASC LIMIT 15";
|
||||
|
||||
} else {
|
||||
$sql = "SELECT DISTINCT val FROM (
|
||||
SELECT specialite AS val
|
||||
FROM praticien
|
||||
WHERE specialite IS NOT NULL AND specialite <> ''
|
||||
UNION ALL
|
||||
SELECT CONCAT(prenom, ' ', nom) AS val
|
||||
FROM praticien
|
||||
WHERE prenom IS NOT NULL AND prenom <> '' AND nom IS NOT NULL AND nom <> ''
|
||||
UNION ALL
|
||||
SELECT prenom AS val
|
||||
FROM praticien
|
||||
WHERE prenom IS NOT NULL AND prenom <> ''
|
||||
UNION ALL
|
||||
SELECT nom AS val
|
||||
FROM praticien
|
||||
WHERE nom IS NOT NULL AND nom <> ''
|
||||
) t
|
||||
WHERE 1";
|
||||
|
||||
if ($q !== '') {
|
||||
$sql .= " AND LOWER(val) LIKE :q";
|
||||
$params[':q'] = mb_strtolower($q, 'UTF-8') . '%';
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY (LOWER(val) LIKE :qprefix) DESC, val ASC LIMIT 15";
|
||||
$params[':qprefix'] = ($q !== '') ? (mb_strtolower($q, 'UTF-8') . '%') : '';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
echo json_encode($stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Helpers
|
||||
========================= */
|
||||
function h($v): string
|
||||
{return htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8');}
|
||||
$reqUri = h($_SERVER['REQUEST_URI'] ?? '/');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?php echo h($lang ?? 'ru') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title><?php echo h($translations['seo_index_title'] ?? '') ?></title>
|
||||
<meta name="description" content="<?php echo h($translations['seo_index_desc'] ?? '') ?>">
|
||||
<meta name="keywords" content="<?php echo h($translations['seo_index_keywords'] ?? '') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="language" content="<?php echo h($lang ?? 'ru') ?>">
|
||||
|
||||
<!-- ✅ Canonical + Hreflang (SEO multilingue) -->
|
||||
<link rel="canonical" href="https://uslugi.fr<?php echo $reqUri ?>">
|
||||
<link rel="alternate" hreflang="ru" href="https://uslugi.fr/ru/">
|
||||
<link rel="alternate" hreflang="fr" href="https://uslugi.fr/fr/">
|
||||
<link rel="alternate" hreflang="x-default" href="https://uslugi.fr/">
|
||||
|
||||
<!-- ✅ Open Graph -->
|
||||
<meta property="og:title" content="<?php echo h($translations['seo_index_title'] ?? '') ?>">
|
||||
<meta property="og:description" content="<?php echo h($translations['seo_index_desc'] ?? '') ?>">
|
||||
<meta property="og:image" content="https://uslugi.fr/public/uploads/img/logo_u.png">
|
||||
<meta property="og:url" content="https://uslugi.fr<?php echo $reqUri ?>">
|
||||
<meta property="og:type" content="website">
|
||||
|
||||
<!-- PWA -->
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<meta name="theme-color" content="#38378B">
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/public/uploads/img/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/public/uploads/img/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/public/uploads/img/favicon-96x96.png">
|
||||
<link rel="icon" href="/public/uploads/img/favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" type="image/svg+xml" href="/public/uploads/img/favicon.svg">
|
||||
<meta name="apple-mobile-web-app-title" content="Uslugi.fr">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/public/uploads/img/apple-touch-icon.png">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
|
||||
<!-- DNS Prefetch -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net">
|
||||
<link rel="dns-prefetch" href="//fonts.googleapis.com">
|
||||
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<?php if (! empty($logged)): ?>
|
||||
<link rel="stylesheet" href="<?php echo h(asset('/includes/site_style.css')) ?>">
|
||||
<?php endif; ?>
|
||||
<link rel="stylesheet" href="<?php echo h(asset('/includes/custom_style.css')) ?>">
|
||||
<link rel="stylesheet" href="<?php echo h(asset('/includes/index_style.css')) ?>">
|
||||
<link rel="stylesheet" href="<?php echo h(asset('/includes/mobil_style.css')) ?>">
|
||||
<?php include_once __DIR__ . '/includes/tracking.php'; ?>
|
||||
<style>
|
||||
.site-header
|
||||
{
|
||||
background: #FFF;
|
||||
border-bottom: 0px solid rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.site-footer
|
||||
{
|
||||
background: #FFF;
|
||||
border-top: 0px solid rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
</style>
|
||||
<!-- ✅ Schema (simple, tu peux enrichir plus tard) -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context":"https://schema.org",
|
||||
"@type":"LocalBusiness",
|
||||
"name":"Uslugi.fr",
|
||||
"url":"https://uslugi.fr",
|
||||
"logo":"https://uslugi.fr/public/uploads/img/logo.png",
|
||||
"address":{"@type":"PostalAddress","addressCountry":"FR"}
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php if (! empty($logged)):
|
||||
include_header_clean(__DIR__ . '/public/includes/header.php');
|
||||
else: ?>
|
||||
|
||||
<!-- Header public identique -->
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
<div class="header-left">
|
||||
<div class="brand">
|
||||
<img src="/public/uploads/img/logo_u.png" alt="uslugi.fr" class="logo-mobile">
|
||||
<img src="/public/uploads/img/logo.png" alt="uslugi.fr" class="logo-desktop">
|
||||
</div>
|
||||
<div class="lang-switch">
|
||||
<?php require __DIR__ . '/includes/menu_langue.php'; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="header-actions">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?php echo h($translations['btn_se_connecter'] ?? '') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo h($translations['ja_spec'] ?? '') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="<?php echo h($translations['help'] ?? 'Помощь') ?>">?</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?php echo h($translations['kak_rabotaet'] ?? '') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo h($translations['pro_nas'] ?? '') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo h($translations['faq'] ?? '') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo h($translations['nam_pisat'] ?? '') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- HERO -->
|
||||
<section class="hero">
|
||||
<div class="home-panel" role="region" aria-label="<?php echo h($translations['home_panel_aria'] ?? 'Accueil') ?>">
|
||||
<div class="container hero-inner">
|
||||
|
||||
<!-- PWA Install floating button (mobile only, hidden by default) ✅ -->
|
||||
<button id="pwaInstallBtn" class="pwa-install d-none" type="button" aria-label="Installer USLUGI">
|
||||
⤓ Uslugi
|
||||
</button>
|
||||
|
||||
<!-- iOS helper (hidden by default) ✅ -->
|
||||
<div id="pwaIosHint" class="pwa-ios-hint d-none" role="dialog" aria-modal="true">
|
||||
<div class="pwa-ios-card">
|
||||
<div class="pwa-ios-title">USLUGI.FR</div>
|
||||
<div class="pwa-ios-text">
|
||||
На iPhone: нажмите (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-up" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M3.5 6a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5h-2a.5.5 0 0 1 0-1h2A1.5 1.5 0 0 1 14 6.5v8a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 14.5v-8A1.5 1.5 0 0 1 3.5 5h2a.5.5 0 0 1 0 1z"/>
|
||||
<path fill-rule="evenodd" d="M7.646.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 1.707V10.5a.5.5 0 0 1-1 0V1.707L5.354 3.854a.5.5 0 1 1-.708-.708z"/>
|
||||
</svg>) <b>Поделиться,</b> затем <b>Добавить на экран</b>.<br><br>
|
||||
Sur iPhone : appuie sur <b>Partager</b> (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-up" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M3.5 6a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5h-2a.5.5 0 0 1 0-1h2A1.5 1.5 0 0 1 14 6.5v8a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 14.5v-8A1.5 1.5 0 0 1 3.5 5h2a.5.5 0 0 1 0 1z"/>
|
||||
<path fill-rule="evenodd" d="M7.646.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708L8.5 1.707V10.5a.5.5 0 0 1-1 0V1.707L5.354 3.854a.5.5 0 1 1-.708-.708z"/>
|
||||
</svg>), puis <b>Sur l'écran d'accueil</b>.
|
||||
</div>
|
||||
<button id="pwaIosClose" class="pwa-ios-close" type="button">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<h1 class="hero-title">
|
||||
<?php echo($translations['titre_home'] ?? '') ?>
|
||||
<span class="visually-hidden">
|
||||
<?php echo h($translations['boostseo_home_h1_suffix'] ?? '') ?>
|
||||
</span>
|
||||
</h1>
|
||||
<p class="visually-hidden">
|
||||
<?php echo h($translations['boostseo_home_intro'] ?? '') ?>
|
||||
</p>
|
||||
<center><h5><?php echo($translations['sous_titre_home'] ?? '') ?></h5></center>
|
||||
<br>
|
||||
<?php
|
||||
$chipKeysRow1 = ['avocats', 'notarius', 'rieltori'];
|
||||
$chipKeysRow2 = ['vrachi', 'psychologues', 'consultants'];
|
||||
$chipKeysRow3 = ['perevod', 'repetitori', 'drugie'];
|
||||
|
||||
$renderChipLinks = function (array $keys) use ($translations) {
|
||||
foreach ($keys as $k) {
|
||||
$label = $translations[$k] ?? $k;
|
||||
$slug = seo_spec_slug_from_key($k);
|
||||
|
||||
$href = '/recherche/';
|
||||
if ($slug !== null && $slug !== '') {
|
||||
$href .= rawurlencode($slug) . '/';
|
||||
}
|
||||
|
||||
echo '<a class="chip chip-link" href="' . h($href) . '">' . h($label) . '</a>';
|
||||
}
|
||||
};
|
||||
?>
|
||||
<!--<h2 class="home-h2"><?php echo h($translations['home_popular_specialists'] ?? '') ?></h2>-->
|
||||
<h2 class="visually-hidden">
|
||||
<?php echo h($translations['boostseo_home_h2_categories'] ?? '') ?>
|
||||
</h2>
|
||||
<div class="row"><?php $renderChipLinks($chipKeysRow1); ?></div>
|
||||
<div class="row"><?php $renderChipLinks($chipKeysRow2); ?></div>
|
||||
<div class="row"><?php $renderChipLinks($chipKeysRow3); ?></div>
|
||||
|
||||
<br>
|
||||
<h2 class="visually-hidden">
|
||||
<?php echo h($translations['boostseo_home_h2_recent'] ?? '') ?>
|
||||
</h2>
|
||||
<div class="hp-list">
|
||||
<?php
|
||||
try {
|
||||
|
||||
/* ======================================================
|
||||
1️⃣ On récupère 50 IDs récents avec photo + abonnement actif
|
||||
====================================================== */
|
||||
$ids = $pdo->query("
|
||||
SELECT id
|
||||
FROM praticien
|
||||
WHERE photo IS NOT NULL
|
||||
AND photo <> ''
|
||||
AND date_expiration >= NOW()
|
||||
ORDER BY id DESC
|
||||
LIMIT 100
|
||||
")->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
if (! $ids) {
|
||||
throw new Exception('Aucun praticien');
|
||||
}
|
||||
|
||||
/* ======================================================
|
||||
2️⃣ On mélange et on prend 4
|
||||
====================================================== */
|
||||
shuffle($ids);
|
||||
$ids = array_slice($ids, 0, 4);
|
||||
|
||||
/* ======================================================
|
||||
3️⃣ On récupère les 4 profils
|
||||
====================================================== */
|
||||
$placeholders = implode(',', array_fill(0, count($ids), '?'));
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
p.id,
|
||||
COALESCE(NULLIF(pt.nom_affiche, ''), p.nom) AS nom,
|
||||
COALESCE(NULLIF(pt.prenom_affiche, ''), p.prenom) AS prenom,
|
||||
COALESCE(NULLIF(pt.specialite, ''), p.specialite) AS specialite,
|
||||
p.photo
|
||||
FROM praticien p
|
||||
LEFT JOIN praticien_traduction pt
|
||||
ON pt.praticien_id = p.id
|
||||
AND pt.langue = ?
|
||||
WHERE p.id IN ($placeholders)
|
||||
");
|
||||
|
||||
$stmt->execute(array_merge([$lang], $ids));
|
||||
$randomPros = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (! $randomPros) {
|
||||
throw new Exception('Aucun praticien');
|
||||
}
|
||||
/* ======================================================
|
||||
3️⃣ Notes
|
||||
====================================================== */
|
||||
function percent_from_5($note)
|
||||
{
|
||||
$n = max(0, min(5, (float) $note));
|
||||
return (int) round($n / 5 * 100);
|
||||
}
|
||||
|
||||
$ratingsById = [];
|
||||
|
||||
$stRatings = $pdo->prepare("
|
||||
SELECT praticien_id, ROUND(AVG(note),1) AS m, COUNT(*) AS c
|
||||
FROM avis_praticien
|
||||
WHERE statut='publie' AND praticien_id IN ($placeholders)
|
||||
GROUP BY praticien_id
|
||||
");
|
||||
$stRatings->execute($ids);
|
||||
|
||||
foreach ($stRatings->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||
$ratingsById[(int) $r['praticien_id']] = [
|
||||
'm' => (float) $r['m'],
|
||||
'c' => (int) $r['c'],
|
||||
];
|
||||
}
|
||||
|
||||
/* ======================================================
|
||||
4️⃣ Affichage
|
||||
====================================================== */
|
||||
foreach ($randomPros as $rp):
|
||||
|
||||
$pid = (int) $rp['id'];
|
||||
|
||||
$photoName = ltrim((string) $rp['photo'], '/');
|
||||
$rpImg = "/public/uploads/" . $photoName;
|
||||
$abs = APP_HTDOCS . "/public/uploads/" . $photoName;
|
||||
|
||||
if (! $photoName || ! is_file($abs)) {
|
||||
$rpImg = "/public/uploads/img/user_placeholder.png";
|
||||
}
|
||||
|
||||
$fullName = trim(($rp['prenom'] ?? '') . ' ' . ($rp['nom'] ?? ''));
|
||||
$spec = trim((string) ($rp['specialite'] ?? ''));
|
||||
$detailUrl = "/detail_public.php?id=" . $pid;
|
||||
|
||||
$hour = random_int(9, 18);
|
||||
$availability = ($translations['home_online_at'] ?? 'Онлайн:') . ' ' . sprintf('%02d:00', $hour);
|
||||
|
||||
$stats = $ratingsById[$pid] ?? ['m' => 0, 'c' => 0];
|
||||
$note = (float) $stats['m'];
|
||||
$count = (int) $stats['c'];
|
||||
$w = percent_from_5($note);
|
||||
|
||||
?>
|
||||
<article class="hp-card">
|
||||
|
||||
<div class="hp-row1">
|
||||
<a href="<?php echo h($detailUrl) ?>" class="hp-avatarLink">
|
||||
<img class="hp-avatar" src="<?php echo h($rpImg) ?>" alt="<?php echo h($fullName) ?>" width="56" height="56" loading="lazy">
|
||||
</a>
|
||||
|
||||
<div class="hp-main">
|
||||
<a href="<?php echo h($detailUrl) ?>" class="hp-avatarLink">
|
||||
<p class="hp-name"><?php echo h($fullName) ?></p>
|
||||
</a>
|
||||
<div class="hp-spec">
|
||||
<?php
|
||||
$text = $spec ?: ($translations['home_specialist_fallback'] ?? '');
|
||||
$words = preg_split('/\s+/', trim($text));
|
||||
echo h(implode(' ', array_slice($words, 0, 7)));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hp-rating">
|
||||
<?php if ($count > 0): ?>
|
||||
<div class="hp-stars">
|
||||
<div class="stars-base">★★★★★</div>
|
||||
<div class="stars-fill" style="width:<?php echo (int) $w ?>%">★★★★★</div>
|
||||
</div>
|
||||
|
||||
<div class="hp-note">
|
||||
<?php echo number_format($note, 1, ',', ' ') ?>/5
|
||||
<span class="text-muted">(<?php echo (int) $count ?>)</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hp-row2">
|
||||
<div class="hp-online">
|
||||
<span>📅</span>
|
||||
<span><?php echo h($availability) ?></span>
|
||||
</div>
|
||||
|
||||
<a class="hp-btn"
|
||||
href="/public/client/reserver_rdv.php?praticien_id=<?php echo $pid ?>">
|
||||
<?php echo h($translations['home_btn_book'] ?? '') ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</article>
|
||||
<?php
|
||||
endforeach;
|
||||
|
||||
} catch (Throwable $e) {
|
||||
// silencieux volontaire
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<br><br>
|
||||
<form class="searchbar" action="/recherche" method="get" id="searchForm">
|
||||
<div class="search-icon">🔍</div>
|
||||
|
||||
<div class="input-wrap">
|
||||
<input type="text"
|
||||
id="specialite"
|
||||
name="specialite"
|
||||
autocomplete="off"
|
||||
placeholder="<?php echo h($translations['n_special'] ?? '') ?>"
|
||||
aria-label="Специальность">
|
||||
<ul class="suggest" id="sg-specialite" hidden></ul>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="input-wrap">
|
||||
<input type="text"
|
||||
id="ville"
|
||||
name="ville"
|
||||
autocomplete="off"
|
||||
placeholder="<?php echo h($translations['gde'] ?? '') ?>"
|
||||
aria-label="Город">
|
||||
<ul class="suggest" id="sg-ville" hidden></ul>
|
||||
</div>
|
||||
|
||||
<button class="hp-btn btn-find--inbar" type="submit">
|
||||
<?php echo h($translations['naiti'] ?? '') ?>
|
||||
</button>
|
||||
</form><br>
|
||||
<div class="spec-cta-wrap">
|
||||
<h3><?php echo h($translations['choix_pro_titre_home'] ?? '') ?></h3>
|
||||
<p><!--<?php echo h($translations['choix_pro_texte_court'] ?? '') ?>--></p>
|
||||
<a class="spec-cta" href="/registration.php">
|
||||
<span class="spec-cta__label"><?php echo h($translations['titre_spec'] ?? '') ?></span>
|
||||
</a>
|
||||
</div>
|
||||
<br>
|
||||
<!--<div class="hp-all">
|
||||
<a href="/result_search.php">
|
||||
<?php echo h($translations['smotret_vsex'] ?? '') ?>
|
||||
</a>
|
||||
</div>-->
|
||||
<br>
|
||||
|
||||
|
||||
<?php include __DIR__ . '/form_index.php'; ?>
|
||||
|
||||
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<div class="visually-hidden">
|
||||
<h2><?php echo h($translations['boostseo_home_h2_cities'] ?? '') ?></h2>
|
||||
<p><?php echo h($translations['boostseo_home_cities_text'] ?? '') ?></p>
|
||||
</div>
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?php echo $translations['copyr'] ?? '' ?><a href="/terms_fr.php" target="_blank"></a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- ✅ Scripts recherche + submit (chips = liens donc pas de JS chips) -->
|
||||
<script src="/js/home.js"></script>
|
||||
|
||||
<!-- ✅ Bootstrap -->
|
||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<?php include __DIR__ . '/includes/accepter_cookies.php'; ?>
|
||||
</body>
|
||||
</html>
|
||||
+39
-39
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
?>
|
||||
|
||||
@@ -7,15 +7,15 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= $translations['insc_praticien_title'] ?></title>
|
||||
<title><?php echo $translations['insc_praticien_title'] ?></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
|
||||
|
||||
.toggle-password {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
@@ -94,13 +94,13 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="Помощь">?</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?= $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?= $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?= $translations['nam_pisat'] ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo $translations['kak_rabotaet'] ?></a></a></li>
|
||||
<li><a href="/about.php"><?php echo $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo $translations['nam_pisat'] ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@@ -109,8 +109,8 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<div class="auth-center">
|
||||
<?php require __DIR__ . '/choisir_abb.php'; ?>
|
||||
<div class="card shadow-sm p-4" style="min-width: 380px; max-width: 480px; width: 100%; margin:40px auto;">
|
||||
|
||||
<h3 class="mb-4 text-center"><?= $translations['insc_praticien_title'] ?></h3>
|
||||
|
||||
<h3 class="mb-4 text-center"><?php echo $translations['insc_praticien_title'] ?></h3>
|
||||
|
||||
<form id="form-inscription" method="POST" action="traitement_inscription_praticien.php">
|
||||
<!-- Champ SIREN/SIRET -->
|
||||
@@ -120,7 +120,7 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
name="siret"
|
||||
id="siret"
|
||||
class="form-control"
|
||||
placeholder="<?= $translations['placeholder_siret'] ?>"
|
||||
placeholder="<?php echo $translations['placeholder_siret'] ?>"
|
||||
required
|
||||
maxlength="17"
|
||||
inputmode="numeric"
|
||||
@@ -128,22 +128,22 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<div id="siret-feedback" class="message-erreur" style="display:none;"></div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="text" name="prenom" class="form-control" placeholder="<?= $translations['placeholder_prenom'] ?>" required>
|
||||
<input type="text" name="prenom" class="form-control" placeholder="<?php echo $translations['placeholder_prenom'] ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<input type="text" name="nom" class="form-control" placeholder="<?= $translations['placeholder_nom'] ?>" required>
|
||||
<input type="text" name="nom" class="form-control" placeholder="<?php echo $translations['placeholder_nom'] ?>" required>
|
||||
</div>
|
||||
<div class="mb-1">
|
||||
<input type="email" name="email" id="email" class="form-control" placeholder="<?= $translations['email_placeholder'] ?>" required>
|
||||
<input type="email" name="email" id="email" class="form-control" placeholder="<?php echo $translations['email_placeholder'] ?>" required>
|
||||
</div>
|
||||
<div class="message-erreur" id="email-erreur"><?= addslashes($translations['email_deja_utilise']) ?></div>
|
||||
<div class="message-erreur" id="email-erreur"><?php echo addslashes($translations['email_deja_utilise']) ?></div>
|
||||
|
||||
<div class="mb-3 position-relative">
|
||||
<input type="password" name="mot_de_passe" id="mot_de_passe" class="form-control" placeholder="<?= $translations['motdepasse_placeholder'] ?>" required>
|
||||
<input type="password" name="mot_de_passe" id="mot_de_passe" class="form-control" placeholder="<?php echo $translations['motdepasse_placeholder'] ?>" required>
|
||||
<span class="toggle-password" onclick="togglePassword('mot_de_passe')">👁️</span>
|
||||
</div>
|
||||
|
||||
<div id="niveau-securite" class="mb-2 text-muted"><?= $translations['mdp_regle_min'] ?></div>
|
||||
<div id="niveau-securite" class="mb-2 text-muted"><?php echo $translations['mdp_regle_min'] ?></div>
|
||||
|
||||
<div class="strength-bar mb-3">
|
||||
<div class="strength-fill"></div>
|
||||
@@ -157,7 +157,7 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
name="confirm_mot_de_passe"
|
||||
id="confirm_mot_de_passe"
|
||||
class="form-control"
|
||||
placeholder="<?= $translations['confirm_mdp_placeholder'] ?? 'Confirmer le mot de passe' ?>"
|
||||
placeholder="<?php echo $translations['confirm_mdp_placeholder'] ?? 'Confirmer le mot de passe' ?>"
|
||||
required
|
||||
autocomplete="new-password">
|
||||
<span class="toggle-password" onclick="togglePassword('confirm_mot_de_passe')">👁️</span>
|
||||
@@ -168,14 +168,14 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
<label class="chk-wrap">
|
||||
<input type="checkbox" id="accept_cgu" name="accept_cgu" required>
|
||||
<span class="chk-box" aria-hidden="true"></span>
|
||||
<span class="chk-label"><?= $translations['cgu_label_html'] ?></span>
|
||||
<span class="chk-label"><?php echo $translations['cgu_label_html'] ?></span>
|
||||
</label>
|
||||
<div class="message-erreur" id="cgu-error" aria-live="polite" style="display:none;">
|
||||
<?= htmlspecialchars($translations['cgu_obligatoire'], ENT_QUOTES, 'UTF-8') ?>
|
||||
<?php echo htmlspecialchars($translations['cgu_obligatoire'], ENT_QUOTES, 'UTF-8') ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100"><?= $translations['btn_sinscrire'] ?></button>
|
||||
<button type="submit" class="btn btn-primary w-100"><?php echo $translations['btn_sinscrire'] ?></button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@@ -188,8 +188,8 @@ require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
const feedback = document.getElementById('confirm-feedback');
|
||||
|
||||
const MSGS = {
|
||||
mismatch: '<?= addslashes($translations["mdp_non_identiques"] ?? "Les mots de passe ne correspondent pas.") ?>',
|
||||
ok: '<?= addslashes($translations["mdp_identiques_ok"] ?? "Les mots de passe correspondent.") ?>'
|
||||
mismatch: '<?php echo addslashes($translations["mdp_non_identiques"] ?? "Les mots de passe ne correspondent pas.") ?>',
|
||||
ok: '<?php echo addslashes($translations["mdp_identiques_ok"] ?? "Les mots de passe correspondent.") ?>'
|
||||
};
|
||||
|
||||
function showOk(){
|
||||
@@ -231,12 +231,12 @@ function togglePassword(id) {
|
||||
}
|
||||
}
|
||||
// Traductions envoyées depuis PHP
|
||||
const EMAIL_TAKEN = '<?= addslashes($translations['email_deja_utilise']) ?>';
|
||||
const EMAIL_TAKEN = '<?php echo addslashes($translations['email_deja_utilise']) ?>';
|
||||
const T = {
|
||||
rule: '<?= addslashes($translations['mdp_regle_min']) ?>',
|
||||
weak: '<?= addslashes($translations['securite_faible']) ?>',
|
||||
medium: '<?= addslashes($translations['securite_moyen']) ?>',
|
||||
strong: '<?= addslashes($translations['securite_fort']) ?>'
|
||||
rule: '<?php echo addslashes($translations['mdp_regle_min']) ?>',
|
||||
weak: '<?php echo addslashes($translations['securite_faible']) ?>',
|
||||
medium: '<?php echo addslashes($translations['securite_moyen']) ?>',
|
||||
strong: '<?php echo addslashes($translations['securite_fort']) ?>'
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -268,11 +268,11 @@ function luhnCheck(num) {
|
||||
let lastQueried = '';
|
||||
|
||||
const MSG = {
|
||||
invalide: '<?= addslashes($translations["siret_format_invalide"]) ?>',
|
||||
valide: '<?= addslashes($translations["siret_valide_format"]) ?>',
|
||||
existe: '<?= addslashes($translations["siret_trouve"]) ?>',
|
||||
nexiste: '<?= addslashes($translations["siret_non_trouve"]) ?>',
|
||||
attente: '<?= addslashes($translations["siret_verification_en_cours"] ?? "Vérification en cours…") ?>'
|
||||
invalide: '<?php echo addslashes($translations["siret_format_invalide"]) ?>',
|
||||
valide: '<?php echo addslashes($translations["siret_valide_format"]) ?>',
|
||||
existe: '<?php echo addslashes($translations["siret_trouve"]) ?>',
|
||||
nexiste: '<?php echo addslashes($translations["siret_non_trouve"]) ?>',
|
||||
attente: '<?php echo addslashes($translations["siret_verification_en_cours"] ?? "Vérification en cours…") ?>'
|
||||
};
|
||||
|
||||
function formatSiret(value) {
|
||||
@@ -403,7 +403,7 @@ function luhnCheck(num) {
|
||||
</div>
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@
|
||||
// --- start when allowed ---
|
||||
function start() {
|
||||
if (!consentOk()) return;
|
||||
initMatomo();
|
||||
//initMatomo();
|
||||
initGA(); // décommente si tu veux activer GA aussi
|
||||
}
|
||||
|
||||
|
||||
+40
-41
@@ -1,40 +1,39 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/bootstrap_global.php';
|
||||
|
||||
|
||||
// Sécurité : accès autorisé uniquement après vérification du code
|
||||
if (! isset($_SESSION['reset_email'], $_SESSION['code_valide']) || ! $_SESSION['code_valide']) {
|
||||
header("Location: mdp_oublie.php");
|
||||
exit;
|
||||
header("Location: mdp_oublie.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
$erreur = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$mdp1 = $_POST['mot_de_passe'] ?? '';
|
||||
$mdp2 = $_POST['confirm_mot_de_passe'] ?? '';
|
||||
$mdp1 = $_POST['mot_de_passe'] ?? '';
|
||||
$mdp2 = $_POST['confirm_mot_de_passe'] ?? '';
|
||||
|
||||
if (strlen($mdp1) < 8 || $mdp1 !== $mdp2) {
|
||||
$erreur = $translations['erreur_mdp_invalides'];
|
||||
} else {
|
||||
$hash = password_hash($mdp1, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE compte SET mot_de_passe = :hash WHERE email = :email");
|
||||
$stmt->execute([
|
||||
'hash' => $hash,
|
||||
'email' => $_SESSION['reset_email'],
|
||||
]);
|
||||
if (strlen($mdp1) < 8 || $mdp1 !== $mdp2) {
|
||||
$erreur = $translations['erreur_mdp_invalides'];
|
||||
} else {
|
||||
$hash = password_hash($mdp1, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE compte SET mot_de_passe = :hash WHERE email = :email");
|
||||
$stmt->execute([
|
||||
'hash' => $hash,
|
||||
'email' => $_SESSION['reset_email'],
|
||||
]);
|
||||
|
||||
// Nettoyage session
|
||||
$lang = $_SESSION['lang'] ?? 'ru';
|
||||
session_unset();
|
||||
session_destroy();
|
||||
session_start();
|
||||
$_SESSION['lang'] = $lang;
|
||||
// Nettoyage session
|
||||
$lang = $_SESSION['lang'] ?? 'ru';
|
||||
session_unset();
|
||||
session_destroy();
|
||||
session_start();
|
||||
$_SESSION['lang'] = $lang;
|
||||
|
||||
$success = $translations['success_mdp_mis_a_jour'];
|
||||
$success = $translations['success_mdp_mis_a_jour'];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -42,12 +41,12 @@
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= $translations['nouveau_mdp_title'] ?></title>
|
||||
<title><?php echo $translations['nouveau_mdp_title'] ?></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<style>
|
||||
.strength-bar {
|
||||
@@ -94,7 +93,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<nav class="header-actions">
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
@@ -102,17 +101,17 @@
|
||||
<div class="main">
|
||||
|
||||
<div class="card shadow-sm p-4" style="min-width: 380px; max-width: 480px; width: 100%;">
|
||||
<h3 class="mb-4 text-center"><?= $translations['nouveau_mdp_h3'] ?></h3>
|
||||
<h3 class="mb-4 text-center"><?php echo $translations['nouveau_mdp_h3'] ?></h3>
|
||||
|
||||
<?php if (!empty($erreur)): ?>
|
||||
<?php if (! empty($erreur)): ?>
|
||||
<div class="alert alert-danger py-2"><?php echo htmlspecialchars($erreur); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($success)): ?>
|
||||
<?php if (! empty($success)): ?>
|
||||
<div class="alert alert-primary py-2 text-center">
|
||||
<div><?= htmlspecialchars($success) ?></div>
|
||||
<div><?php echo htmlspecialchars($success) ?></div>
|
||||
</div>
|
||||
<a href="connexion.php" class="btn btn-danger fw-bold"><?= $translations['btn_se_connecter'] ?></a>
|
||||
<a href="connexion.php" class="btn btn-danger fw-bold"><?php echo $translations['btn_se_connecter'] ?></a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (empty($success)): ?>
|
||||
@@ -120,11 +119,11 @@
|
||||
|
||||
<!-- Nouveau mot de passe -->
|
||||
<div class="mb-3 field-wrapper">
|
||||
<input type="password" name="mot_de_passe" id="mot_de_passe" class="form-control" placeholder="<?= $translations['nouveau_mdp_placeholder'] ?>" required>
|
||||
<input type="password" name="mot_de_passe" id="mot_de_passe" class="form-control" placeholder="<?php echo $translations['nouveau_mdp_placeholder'] ?>" required>
|
||||
<span class="toggle-password" onclick="toggle('mot_de_passe')">👁️</span>
|
||||
</div>
|
||||
|
||||
<div id="niveau-securite" class="mb-2 text-muted"><?= $translations['mdp_regle_min'] ?></div>
|
||||
<div id="niveau-securite" class="mb-2 text-muted"><?php echo $translations['mdp_regle_min'] ?></div>
|
||||
|
||||
<div class="strength-bar mb-3">
|
||||
<div class="strength-fill"></div>
|
||||
@@ -134,21 +133,21 @@
|
||||
|
||||
<!-- Confirmation mot de passe -->
|
||||
<div class="mb-4 field-wrapper">
|
||||
<input type="password" name="confirm_mot_de_passe" id="confirm_mot_de_passe" class="form-control" placeholder="<?= $translations['confirm_mdp_placeholder'] ?>" required>
|
||||
<input type="password" name="confirm_mot_de_passe" id="confirm_mot_de_passe" class="form-control" placeholder="<?php echo $translations['confirm_mdp_placeholder'] ?>" required>
|
||||
<span class="toggle-password" onclick="toggle('confirm_mot_de_passe')">👁️</span>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100"><?= $translations['btn_valider'] ?></button>
|
||||
<button type="submit" class="btn btn-primary w-100"><?php echo $translations['btn_valider'] ?></button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const T = {
|
||||
rule: '<?= addslashes($translations['mdp_regle_min']) ?>',
|
||||
weak: '<?= addslashes($translations['securite_faible']) ?>',
|
||||
medium: '<?= addslashes($translations['securite_moyen']) ?>',
|
||||
strong: '<?= addslashes($translations['securite_fort']) ?>'
|
||||
rule: '<?php echo addslashes($translations['mdp_regle_min']) ?>',
|
||||
weak: '<?php echo addslashes($translations['securite_faible']) ?>',
|
||||
medium: '<?php echo addslashes($translations['securite_moyen']) ?>',
|
||||
strong: '<?php echo addslashes($translations['securite_fort']) ?>'
|
||||
};
|
||||
|
||||
function toggle(id) {
|
||||
@@ -196,7 +195,7 @@ document.getElementById('mot_de_passe').addEventListener('input', function () {
|
||||
</div>
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
+38
-3
@@ -61,8 +61,10 @@ return [
|
||||
'logo_titre' => '<a href=index.php>USLUGI.FR</a>',
|
||||
'home' => 'Accueil',
|
||||
'ja_spec' => 'Connexion',
|
||||
'titre_home' => 'Trouvez votre spécialiste<br> en France',
|
||||
'sous_titre_home' => 'Les professionnels avec SIRET,<br> recherche, chat, prise de rendez-vous, visio',
|
||||
'titre_home' => '<font color="#000">Contacts utiles</font> <br>en France.',
|
||||
'choix_pro_titre_home' => '<font color="#000"><b>Vous connaissez un spécialiste ?</b></font> Partagez ses coordonnées!',
|
||||
'choix_pro_titre_home_banner' => '<font color="#000"><b>Vous êtes spécialiste ?</b></font> Rejoignez-nous !',
|
||||
'sous_titre_home' => 'C\'est bien de savoir<br> à qui s\'adresser !',
|
||||
'titre_spec_index' => 'Tous les spécialistes reçoivent en ligne et en cabinet',
|
||||
'avocats' => 'avocats',
|
||||
'consultants' => 'consultants',
|
||||
@@ -100,7 +102,6 @@ return [
|
||||
'btn_inscription_client' => 'Créer un compte',
|
||||
'choix_type_inscription' => 'Choisissez le type d’inscription',
|
||||
'choix_pro_titre' => '<b>Vous êtes spécialiste</b>',
|
||||
'choix_pro_titre_home' => 'Vous êtes spécialiste?',
|
||||
'choix_pro_texte_court' => 'Rejoignez la plateforme Uslugi',
|
||||
'choix_pro_texte' => 'Rejoignez la plateforme et proposez vos services',
|
||||
'btn_inscription_pro' => 'Créer un compte',
|
||||
@@ -2243,4 +2244,38 @@ Cliquez simplement sur le lien pour vous connecter.<br>',
|
||||
'menu_communication' => 'Communication',
|
||||
'menu_content' => 'Contenu',
|
||||
'menu_maintenance' => 'Maintenance',
|
||||
|
||||
'recom_badge' => 'Recommandation',
|
||||
'recom_title' => 'Recommandez un professionnel',
|
||||
'recom_intro' => 'Vous connaissez un professionnel de confiance ? Partagez ses coordonnées et aidez notre communauté à trouver des personnes compétentes.',
|
||||
|
||||
'recom_fullname_label' => 'Nom et prénom',
|
||||
'recom_fullname_placeholder' => 'Nom et prénom du professionnel',
|
||||
|
||||
'recom_profession_label' => 'Profession / Activité',
|
||||
'recom_profession_placeholder' => 'Exemple : avocat, médecin, traducteur...',
|
||||
|
||||
'recom_location_label' => 'Ville et pays',
|
||||
'recom_location_placeholder' => 'Exemple : Paris, France',
|
||||
|
||||
'recom_phone_label' => 'Téléphone',
|
||||
'recom_phone_placeholder' => '+33 6 00 00 00 00',
|
||||
|
||||
'recom_email_label' => 'E-mail',
|
||||
'recom_email_placeholder' => 'exemple@email.com',
|
||||
|
||||
'recom_website_label' => 'Site internet',
|
||||
'recom_website_placeholder' => 'https://exemple.com',
|
||||
|
||||
'recom_reason_label' => 'Pourquoi recommandez-vous ce professionnel ?',
|
||||
'recom_reason_placeholder' => 'Expliquez brièvement pourquoi vous recommandez cette personne...',
|
||||
|
||||
'recom_submit' => 'Envoyer la recommandation',
|
||||
|
||||
'recom_note' => 'Vous pouvez renseigner les coordonnées dont vous disposez.',
|
||||
|
||||
'recom_success_title' => 'Merci pour votre recommandation !',
|
||||
'recom_success_text' => 'Votre recommandation a bien été envoyée. Merci de contribuer au développement de notre communauté.',
|
||||
'recom_error_popup_title' => 'Erreur',
|
||||
|
||||
];
|
||||
File diff suppressed because it is too large.
Load diff
+38
-3
@@ -60,8 +60,8 @@ return [
|
||||
'logo_titre' => '<a href=index.php>USLUGI.FR</a>',
|
||||
'home' => 'Главная',
|
||||
'ja_spec' => 'Войти',
|
||||
'titre_home' => 'Найдите своего специалиста <br> во Франции',
|
||||
'sous_titre_home' => 'Профессионалы с SIRET<br> Поиск, чат, запись, видеосвязь',
|
||||
'titre_home' => '<font color="#000">Полезные контакты</font> <br>во Франции.',
|
||||
'sous_titre_home' => 'Хорошо, когда знаешь,<br> к кому обратиться!',
|
||||
'titre_spec_index' => 'Все специалисты принимают по записи онлайн',
|
||||
'avocats' => 'адвокаты',
|
||||
'consultants' => 'консультанты',
|
||||
@@ -99,7 +99,8 @@ return [
|
||||
'btn_inscription_client' => 'Зарегистрироваться',
|
||||
'choix_type_inscription' => 'Выберите тип регистрации',
|
||||
'choix_pro_titre' => '<b>Вы специалист</b>',
|
||||
'choix_pro_titre_home' => 'Вы специалист?',
|
||||
'choix_pro_titre_home' => '<font color="#000"><b>Знаете хорошего специалиста?</b></font> Поделитесь контактом!',
|
||||
'choix_pro_titre_home_banner' => '<font color="#000"><b>Вы специалист?</b></font> Присоединяетесь!',
|
||||
'choix_pro_texte_court' => 'Получайте заявки от новых клиентов и предлагайте ваши услуги',
|
||||
'choix_pro_texte' => 'Присоединяйтесь к нашей платформе и предлагайте ваши услуги',
|
||||
'btn_inscription_pro' => 'Зарегистрироваться',
|
||||
@@ -2254,4 +2255,38 @@ return [
|
||||
'menu_communication' => 'Коммуникация',
|
||||
'menu_content' => 'Контент',
|
||||
'menu_maintenance' => 'Обслуживание',
|
||||
|
||||
'recom_badge' => 'Рекомендация специалиста',
|
||||
'recom_title' => 'Порекомендуйте хорошего специалиста',
|
||||
'recom_intro' => 'Знаете проверенного специалиста? Поделитесь его контактами и помогите другим найти надёжного профессионала.',
|
||||
|
||||
'recom_fullname_label' => 'Имя и фамилия',
|
||||
'recom_fullname_placeholder' => 'Имя и фамилия специалиста',
|
||||
|
||||
'recom_profession_label' => 'Профессия / Чем занимается',
|
||||
'recom_profession_placeholder' => 'Например: юрист, врач, переводчик...',
|
||||
|
||||
'recom_location_label' => 'Город и страна',
|
||||
'recom_location_placeholder' => 'Например: Париж, Франция',
|
||||
|
||||
'recom_phone_label' => 'Телефон',
|
||||
'recom_phone_placeholder' => '+33 6 00 00 00 00',
|
||||
|
||||
'recom_email_label' => 'Электронная почта',
|
||||
'recom_email_placeholder' => 'example@email.com',
|
||||
|
||||
'recom_website_label' => 'Сайт',
|
||||
'recom_website_placeholder' => 'https://example.com',
|
||||
|
||||
'recom_reason_label' => 'Почему вы рекомендуете этого специалиста?',
|
||||
'recom_reason_placeholder' => 'Расскажите коротко, почему вы рекомендуете этого человека...',
|
||||
|
||||
'recom_submit' => 'Отправить рекомендацию',
|
||||
|
||||
'recom_note' => 'Контактные данные можно указать, если они вам известны.',
|
||||
|
||||
'recom_success_title' => 'Спасибо за рекомендацию!',
|
||||
'recom_success_text' => 'Ваша рекомендация успешно отправлена. Благодарим за участие в развитии нашего сообщества.',
|
||||
'recom_error_popup_title' => 'Ошибка',
|
||||
|
||||
];
|
||||
File diff suppressed because it is too large.
Load diff
+83
-63
@@ -1,51 +1,71 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void {
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath;
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf;
|
||||
}
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath;
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf;
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($lang ?? 'ru', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<html lang="<?php echo htmlspecialchars($lang ?? 'ru', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title><?= htmlspecialchars($translations['seo_topic_business_title'] ?? 'USLUGI.FR', ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_topic_business_desc'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_topic_business_keywords'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_topic_business_title'] ?? 'USLUGI.FR', ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_topic_business_desc'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_topic_business_keywords'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<style>
|
||||
.topic { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#4b5563; --card:#fff; --border:#e5e7eb; }
|
||||
@@ -64,7 +84,7 @@ function include_header_clean(string $absPath): void {
|
||||
background: color-mix(in oklab, var(--brand) 8%, #fff); border-radius:12px; padding:14px 16px; }
|
||||
</style>
|
||||
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php';?>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -89,22 +109,22 @@ function include_header_clean(string $absPath): void {
|
||||
</div>
|
||||
<nav class="d-flex align-items-center gap-2">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= $translations['btn_se_connecter'] ?></span>
|
||||
<span class="d-none d-sm-inline"><?= $translations['ja_spec'] ?></span>
|
||||
<span class="d-sm-none"><?php echo $translations['btn_se_connecter'] ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo $translations['ja_spec'] ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="<?= htmlspecialchars($translations['aria_help'] ?? 'Помощь') ?>">
|
||||
aria-expanded="false" aria-label="<?php echo htmlspecialchars($translations['aria_help'] ?? 'Помощь') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= $translations['kak_rabotaet'] ?></a></li>
|
||||
<li><a href="/about.php"><?= $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?= $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?= $translations['nam_pisat'] ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo $translations['kak_rabotaet'] ?></a></li>
|
||||
<li><a href="/about.php"><?php echo $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo $translations['nam_pisat'] ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -116,39 +136,39 @@ function include_header_clean(string $absPath): void {
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
|
||||
<h1><?= $translations['topic_business_h1'] ?></h1>
|
||||
<p><?= $translations['topic_business_intro'] ?></p>
|
||||
<h1><?php echo $translations['topic_business_h1'] ?></h1>
|
||||
<p><?php echo $translations['topic_business_intro'] ?></p>
|
||||
|
||||
<div class="toc">
|
||||
<a href="#forms"><?= $translations['topic_business_toc_forms'] ?></a>
|
||||
<a href="#reg"><?= $translations['topic_business_toc_reg'] ?></a>
|
||||
<a href="#tax"><?= $translations['topic_business_toc_tax'] ?></a>
|
||||
<a href="#account"><?= $translations['topic_business_toc_account'] ?></a>
|
||||
<a href="#errors"><?= $translations['topic_business_toc_errors'] ?></a>
|
||||
<a href="#forms"><?php echo $translations['topic_business_toc_forms'] ?></a>
|
||||
<a href="#reg"><?php echo $translations['topic_business_toc_reg'] ?></a>
|
||||
<a href="#tax"><?php echo $translations['topic_business_toc_tax'] ?></a>
|
||||
<a href="#account"><?php echo $translations['topic_business_toc_account'] ?></a>
|
||||
<a href="#errors"><?php echo $translations['topic_business_toc_errors'] ?></a>
|
||||
</div>
|
||||
|
||||
<h2 id="forms"><?= $translations['topic_business_h2_forms'] ?></h2>
|
||||
<p><?= $translations['topic_business_p_forms'] ?></p>
|
||||
<h2 id="forms"><?php echo $translations['topic_business_h2_forms'] ?></h2>
|
||||
<p><?php echo $translations['topic_business_p_forms'] ?></p>
|
||||
|
||||
<h2 id="reg"><?= $translations['topic_business_h2_reg'] ?></h2>
|
||||
<p><?= $translations['topic_business_p_reg'] ?></p>
|
||||
<h2 id="reg"><?php echo $translations['topic_business_h2_reg'] ?></h2>
|
||||
<p><?php echo $translations['topic_business_p_reg'] ?></p>
|
||||
|
||||
<h2 id="tax"><?= $translations['topic_business_h2_tax'] ?></h2>
|
||||
<p><?= $translations['topic_business_p_tax'] ?></p>
|
||||
<h2 id="tax"><?php echo $translations['topic_business_h2_tax'] ?></h2>
|
||||
<p><?php echo $translations['topic_business_p_tax'] ?></p>
|
||||
|
||||
<h2 id="account"><?= $translations['topic_business_h2_account'] ?></h2>
|
||||
<p><?= $translations['topic_business_p_account'] ?></p>
|
||||
<h2 id="account"><?php echo $translations['topic_business_h2_account'] ?></h2>
|
||||
<p><?php echo $translations['topic_business_p_account'] ?></p>
|
||||
|
||||
<h2 id="errors"><?= $translations['topic_business_h2_errors'] ?></h2>
|
||||
<p><?= $translations['topic_business_p_errors'] ?></p>
|
||||
<h2 id="errors"><?php echo $translations['topic_business_h2_errors'] ?></h2>
|
||||
<p><?php echo $translations['topic_business_p_errors'] ?></p>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?= $translations['topic_business_callout_label'] ?></strong>
|
||||
<?= $translations['topic_business_callout_text'] ?>
|
||||
<strong><?php echo $translations['topic_business_callout_label'] ?></strong>
|
||||
<?php echo $translations['topic_business_callout_text'] ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?= $translations['topic_business_cta_find'] ?></a>
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?php echo $translations['topic_business_cta_find'] ?></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -157,7 +177,7 @@ function include_header_clean(string $absPath): void {
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+83
-63
@@ -1,51 +1,71 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void {
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath;
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf;
|
||||
}
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath;
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf;
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($lang ?? 'ru', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<html lang="<?php echo htmlspecialchars($lang ?? 'ru', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title><?= htmlspecialchars($translations['seo_topic_family_title'] ?? 'USLUGI.FR', ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars($translations['seo_topic_family_desc'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars($translations['seo_topic_family_keywords'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<title><?php echo htmlspecialchars($translations['seo_topic_family_title'] ?? 'USLUGI.FR', ENT_QUOTES, 'UTF-8') ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars($translations['seo_topic_family_desc'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars($translations['seo_topic_family_keywords'] ?? '', ENT_QUOTES, 'UTF-8') ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
|
||||
<style>
|
||||
.topic { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#4b5563; --card:#fff; --border:#e5e7eb; }
|
||||
@@ -64,7 +84,7 @@ function include_header_clean(string $absPath): void {
|
||||
background: color-mix(in oklab, var(--brand) 8%, #fff); border-radius:12px; padding:14px 16px; }
|
||||
</style>
|
||||
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php';?>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -89,22 +109,22 @@ function include_header_clean(string $absPath): void {
|
||||
</div>
|
||||
<nav class="d-flex align-items-center gap-2">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= $translations['btn_se_connecter'] ?></span>
|
||||
<span class="d-none d-sm-inline"><?= $translations['ja_spec'] ?></span>
|
||||
<span class="d-sm-none"><?php echo $translations['btn_se_connecter'] ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo $translations['ja_spec'] ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-logo rounded-circle d-inline-flex align-items-center justify-content-center question-btn"
|
||||
type="button" data-bs-toggle="dropdown" data-bs-auto-close="true"
|
||||
aria-expanded="false" aria-label="<?= htmlspecialchars($translations['aria_help'] ?? 'Помощь') ?>">
|
||||
aria-expanded="false" aria-label="<?php echo htmlspecialchars($translations['aria_help'] ?? 'Помощь') ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= $translations['kak_rabotaet'] ?></a></li>
|
||||
<li><a href="/about.php"><?= $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?= $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?= $translations['nam_pisat'] ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo $translations['kak_rabotaet'] ?></a></li>
|
||||
<li><a href="/about.php"><?php echo $translations['pro_nas'] ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo $translations['faq'] ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo $translations['nam_pisat'] ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -116,39 +136,39 @@ function include_header_clean(string $absPath): void {
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
|
||||
<h1><?= $translations['topic_family_h1'] ?></h1>
|
||||
<p><?= $translations['topic_family_intro'] ?></p>
|
||||
<h1><?php echo $translations['topic_family_h1'] ?></h1>
|
||||
<p><?php echo $translations['topic_family_intro'] ?></p>
|
||||
|
||||
<div class="toc">
|
||||
<a href="#mariage"><?= $translations['topic_family_toc_mariage'] ?></a>
|
||||
<a href="#pacs"><?= $translations['topic_family_toc_pacs'] ?></a>
|
||||
<a href="#divorce"><?= $translations['topic_family_toc_divorce'] ?></a>
|
||||
<a href="#children"><?= $translations['topic_family_toc_children'] ?></a>
|
||||
<a href="#docs"><?= $translations['topic_family_toc_docs'] ?></a>
|
||||
<a href="#mariage"><?php echo $translations['topic_family_toc_mariage'] ?></a>
|
||||
<a href="#pacs"><?php echo $translations['topic_family_toc_pacs'] ?></a>
|
||||
<a href="#divorce"><?php echo $translations['topic_family_toc_divorce'] ?></a>
|
||||
<a href="#children"><?php echo $translations['topic_family_toc_children'] ?></a>
|
||||
<a href="#docs"><?php echo $translations['topic_family_toc_docs'] ?></a>
|
||||
</div>
|
||||
|
||||
<h2 id="mariage"><?= $translations['topic_family_h2_mariage'] ?></h2>
|
||||
<p><?= $translations['topic_family_p_mariage'] ?></p>
|
||||
<h2 id="mariage"><?php echo $translations['topic_family_h2_mariage'] ?></h2>
|
||||
<p><?php echo $translations['topic_family_p_mariage'] ?></p>
|
||||
|
||||
<h2 id="pacs"><?= $translations['topic_family_h2_pacs'] ?></h2>
|
||||
<p><?= $translations['topic_family_p_pacs'] ?></p>
|
||||
<h2 id="pacs"><?php echo $translations['topic_family_h2_pacs'] ?></h2>
|
||||
<p><?php echo $translations['topic_family_p_pacs'] ?></p>
|
||||
|
||||
<h2 id="divorce"><?= $translations['topic_family_h2_divorce'] ?></h2>
|
||||
<p><?= $translations['topic_family_p_divorce'] ?></p>
|
||||
<h2 id="divorce"><?php echo $translations['topic_family_h2_divorce'] ?></h2>
|
||||
<p><?php echo $translations['topic_family_p_divorce'] ?></p>
|
||||
|
||||
<h2 id="children"><?= $translations['topic_family_h2_children'] ?></h2>
|
||||
<p><?= $translations['topic_family_p_children'] ?></p>
|
||||
<h2 id="children"><?php echo $translations['topic_family_h2_children'] ?></h2>
|
||||
<p><?php echo $translations['topic_family_p_children'] ?></p>
|
||||
|
||||
<h2 id="docs"><?= $translations['topic_family_h2_docs'] ?></h2>
|
||||
<p><?= $translations['topic_family_p_docs'] ?></p>
|
||||
<h2 id="docs"><?php echo $translations['topic_family_h2_docs'] ?></h2>
|
||||
<p><?php echo $translations['topic_family_p_docs'] ?></p>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?= $translations['topic_family_callout_label'] ?></strong>
|
||||
<?= $translations['topic_family_callout_text'] ?>
|
||||
<strong><?php echo $translations['topic_family_callout_label'] ?></strong>
|
||||
<?php echo $translations['topic_family_callout_text'] ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?= $translations['topic_family_cta_find'] ?></a>
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?php echo $translations['topic_family_cta_find'] ?></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -157,7 +177,7 @@ function include_header_clean(string $absPath): void {
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= $translations['copyr'] ?></p>
|
||||
<p><?php echo $translations['copyr'] ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+92
-72
@@ -1,63 +1,83 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// helpers safe (optionnel mais propre)
|
||||
function t(string $key, string $fallback = ''): string {
|
||||
global $translations;
|
||||
return (string)($translations[$key] ?? $fallback);
|
||||
}
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
// helpers safe (optionnel mais propre)
|
||||
function t(string $key, string $fallback = ''): string
|
||||
{
|
||||
global $translations;
|
||||
return (string) ($translations[$key] ?? $fallback);
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<html lang="<?php echo htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars(t('seo_medecine_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars(t('seo_medecine_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars(t('seo_medecine_keywords'), ENT_QUOTES) ?>">
|
||||
<title><?php echo htmlspecialchars(t('seo_medecine_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars(t('seo_medecine_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars(t('seo_medecine_keywords'), ENT_QUOTES) ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
.topic { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#4b5563; --card:#fff; --border:#e5e7eb; }
|
||||
.topic { font-family: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; color:var(--text); }
|
||||
@@ -76,7 +96,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
.faq dt{ font-weight:600; margin-top:10px; }
|
||||
.faq dd{ margin-left:0; color:var(--muted); }
|
||||
</style>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php';?>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header minimal (logo + actions) -->
|
||||
@@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<nav class="d-flex align-items-center gap-2">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?= t('ja_spec') ?></span>
|
||||
<span class="d-sm-none"><?php echo t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo t('ja_spec') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -113,16 +133,16 @@ function t(string $key, string $fallback = ''): string {
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?= htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
aria-label="<?php echo htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<!-- Menu compact -->
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?= t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?= t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?= t('nam_pisat') ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo t('nam_pisat') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
|
||||
<h1><?= t('medecine_h1') ?></h1>
|
||||
<p><?= t('medecine_intro') ?></p>
|
||||
<h1><?php echo t('medecine_h1') ?></h1>
|
||||
<p><?php echo t('medecine_intro') ?></p>
|
||||
|
||||
<div class="toc">
|
||||
<a href="#gp"><?= t('medecine_toc_gp') ?></a>
|
||||
<a href="#assurance"><?= t('medecine_toc_assurance') ?></a>
|
||||
<a href="#labs"><?= t('medecine_toc_labs') ?></a>
|
||||
<a href="#dentaire"><?= t('medecine_toc_dentaire') ?></a>
|
||||
<a href="#hospital"><?= t('medecine_toc_hospital') ?></a>
|
||||
<a href="#gp"><?php echo t('medecine_toc_gp') ?></a>
|
||||
<a href="#assurance"><?php echo t('medecine_toc_assurance') ?></a>
|
||||
<a href="#labs"><?php echo t('medecine_toc_labs') ?></a>
|
||||
<a href="#dentaire"><?php echo t('medecine_toc_dentaire') ?></a>
|
||||
<a href="#hospital"><?php echo t('medecine_toc_hospital') ?></a>
|
||||
</div>
|
||||
|
||||
<h2 id="gp"><?= t('medecine_h2_gp') ?></h2>
|
||||
<p><?= t('medecine_p_gp') ?></p>
|
||||
<h2 id="gp"><?php echo t('medecine_h2_gp') ?></h2>
|
||||
<p><?php echo t('medecine_p_gp') ?></p>
|
||||
|
||||
<h2 id="assurance"><?= t('medecine_h2_assurance') ?></h2>
|
||||
<p><?= t('medecine_p_assurance') ?></p>
|
||||
<h2 id="assurance"><?php echo t('medecine_h2_assurance') ?></h2>
|
||||
<p><?php echo t('medecine_p_assurance') ?></p>
|
||||
|
||||
<h2 id="labs"><?= t('medecine_h2_labs') ?></h2>
|
||||
<p><?= t('medecine_p_labs') ?></p>
|
||||
<h2 id="labs"><?php echo t('medecine_h2_labs') ?></h2>
|
||||
<p><?php echo t('medecine_p_labs') ?></p>
|
||||
|
||||
<h2 id="dentaire"><?= t('medecine_h2_dentaire') ?></h2>
|
||||
<p><?= t('medecine_p_dentaire') ?></p>
|
||||
<h2 id="dentaire"><?php echo t('medecine_h2_dentaire') ?></h2>
|
||||
<p><?php echo t('medecine_p_dentaire') ?></p>
|
||||
|
||||
<h2 id="hospital"><?= t('medecine_h2_hospital') ?></h2>
|
||||
<p><?= t('medecine_p_hospital') ?></p>
|
||||
<h2 id="hospital"><?php echo t('medecine_h2_hospital') ?></h2>
|
||||
<p><?php echo t('medecine_p_hospital') ?></p>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?= t('medecine_tip_strong') ?></strong> <?= t('medecine_tip_text') ?>
|
||||
<strong><?php echo t('medecine_tip_strong') ?></strong> <?php echo t('medecine_tip_text') ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?= t('medecine_btn_find') ?></a>
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?php echo t('medecine_btn_find') ?></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= t('copyr') ?></p>
|
||||
<p><?php echo t('copyr') ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+92
-72
@@ -1,63 +1,83 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// helper simple
|
||||
function t(string $key, string $fallback = ''): string {
|
||||
global $translations;
|
||||
return (string)($translations[$key] ?? $fallback);
|
||||
}
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
// helper simple
|
||||
function t(string $key, string $fallback = ''): string
|
||||
{
|
||||
global $translations;
|
||||
return (string) ($translations[$key] ?? $fallback);
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<html lang="<?php echo htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars(t('seo_immigration_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars(t('seo_immigration_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars(t('seo_immigration_keywords'), ENT_QUOTES) ?>">
|
||||
<title><?php echo htmlspecialchars(t('seo_immigration_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars(t('seo_immigration_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars(t('seo_immigration_keywords'), ENT_QUOTES) ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
.topic { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#4b5563; --card:#fff; --border:#e5e7eb; }
|
||||
.topic { font-family: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; color:var(--text); }
|
||||
@@ -76,7 +96,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
.faq dt{ font-weight:600; margin-top:10px; }
|
||||
.faq dd{ margin-left:0; color:var(--muted); }
|
||||
</style>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php';?>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header minimal (logo + actions) -->
|
||||
@@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<nav class="d-flex align-items-center gap-2">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?= t('ja_spec') ?></span>
|
||||
<span class="d-sm-none"><?php echo t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo t('ja_spec') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -113,16 +133,16 @@ function t(string $key, string $fallback = ''): string {
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?= htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
aria-label="<?php echo htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<!-- Menu compact -->
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?= t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?= t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?= t('nam_pisat') ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo t('nam_pisat') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
|
||||
<h1><?= t('immigration_h1') ?></h1>
|
||||
<p><?= t('immigration_intro') ?></p>
|
||||
<h1><?php echo t('immigration_h1') ?></h1>
|
||||
<p><?php echo t('immigration_intro') ?></p>
|
||||
|
||||
<div class="toc">
|
||||
<a href="#visa-d"><?= t('immigration_toc_visa_d') ?></a>
|
||||
<a href="#vnj"><?= t('immigration_toc_vnj') ?></a>
|
||||
<a href="#nat"><?= t('immigration_toc_nat') ?></a>
|
||||
<a href="#family"><?= t('immigration_toc_family') ?></a>
|
||||
<a href="#docs"><?= t('immigration_toc_docs') ?></a>
|
||||
<a href="#visa-d"><?php echo t('immigration_toc_visa_d') ?></a>
|
||||
<a href="#vnj"><?php echo t('immigration_toc_vnj') ?></a>
|
||||
<a href="#nat"><?php echo t('immigration_toc_nat') ?></a>
|
||||
<a href="#family"><?php echo t('immigration_toc_family') ?></a>
|
||||
<a href="#docs"><?php echo t('immigration_toc_docs') ?></a>
|
||||
</div>
|
||||
|
||||
<h2 id="visa-d"><?= t('immigration_h2_visa_d') ?></h2>
|
||||
<p><?= t('immigration_p_visa_d') ?></p>
|
||||
<h2 id="visa-d"><?php echo t('immigration_h2_visa_d') ?></h2>
|
||||
<p><?php echo t('immigration_p_visa_d') ?></p>
|
||||
|
||||
<h2 id="vnj"><?= t('immigration_h2_vnj') ?></h2>
|
||||
<p><?= t('immigration_p_vnj') ?></p>
|
||||
<h2 id="vnj"><?php echo t('immigration_h2_vnj') ?></h2>
|
||||
<p><?php echo t('immigration_p_vnj') ?></p>
|
||||
|
||||
<h2 id="nat"><?= t('immigration_h2_nat') ?></h2>
|
||||
<p><?= t('immigration_p_nat') ?></p>
|
||||
<h2 id="nat"><?php echo t('immigration_h2_nat') ?></h2>
|
||||
<p><?php echo t('immigration_p_nat') ?></p>
|
||||
|
||||
<h2 id="family"><?= t('immigration_h2_family') ?></h2>
|
||||
<p><?= t('immigration_p_family') ?></p>
|
||||
<h2 id="family"><?php echo t('immigration_h2_family') ?></h2>
|
||||
<p><?php echo t('immigration_p_family') ?></p>
|
||||
|
||||
<h2 id="docs"><?= t('immigration_h2_docs') ?></h2>
|
||||
<p><?= t('immigration_p_docs') ?></p>
|
||||
<h2 id="docs"><?php echo t('immigration_h2_docs') ?></h2>
|
||||
<p><?php echo t('immigration_p_docs') ?></p>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?= t('immigration_tip_strong') ?></strong> <?= t('immigration_tip_text') ?>
|
||||
<strong><?php echo t('immigration_tip_strong') ?></strong> <?php echo t('immigration_tip_text') ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?= t('immigration_btn_find') ?></a>
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?php echo t('immigration_btn_find') ?></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= t('copyr') ?></p>
|
||||
<p><?php echo t('copyr') ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+92
-72
@@ -1,63 +1,83 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// helper simple
|
||||
function t(string $key, string $fallback = ''): string {
|
||||
global $translations;
|
||||
return (string)($translations[$key] ?? $fallback);
|
||||
}
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
// helper simple
|
||||
function t(string $key, string $fallback = ''): string
|
||||
{
|
||||
global $translations;
|
||||
return (string) ($translations[$key] ?? $fallback);
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<html lang="<?php echo htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars(t('seo_travail_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars(t('seo_travail_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars(t('seo_travail_keywords'), ENT_QUOTES) ?>">
|
||||
<title><?php echo htmlspecialchars(t('seo_travail_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars(t('seo_travail_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars(t('seo_travail_keywords'), ENT_QUOTES) ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
.topic { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#4b5563; --card:#fff; --border:#e5e7eb; }
|
||||
.topic { font-family: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; color:var(--text); }
|
||||
@@ -76,7 +96,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
.faq dt{ font-weight:600; margin-top:10px; }
|
||||
.faq dd{ margin-left:0; color:var(--muted); }
|
||||
</style>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php';?>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header minimal (logo + actions) -->
|
||||
@@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<nav class="d-flex align-items-center gap-2">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?= t('ja_spec') ?></span>
|
||||
<span class="d-sm-none"><?php echo t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo t('ja_spec') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -113,16 +133,16 @@ function t(string $key, string $fallback = ''): string {
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?= htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
aria-label="<?php echo htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<!-- Menu compact -->
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?= t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?= t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?= t('nam_pisat') ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo t('nam_pisat') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
|
||||
<h1><?= t('travail_h1') ?></h1>
|
||||
<p><?= t('travail_intro') ?></p>
|
||||
<h1><?php echo t('travail_h1') ?></h1>
|
||||
<p><?php echo t('travail_intro') ?></p>
|
||||
|
||||
<div class="toc">
|
||||
<a href="#cv"><?= t('travail_toc_cv') ?></a>
|
||||
<a href="#contracts"><?= t('travail_toc_contracts') ?></a>
|
||||
<a href="#rights"><?= t('travail_toc_rights') ?></a>
|
||||
<a href="#dismiss"><?= t('travail_toc_dismiss') ?></a>
|
||||
<a href="#unemployment"><?= t('travail_toc_unemployment') ?></a>
|
||||
<a href="#cv"><?php echo t('travail_toc_cv') ?></a>
|
||||
<a href="#contracts"><?php echo t('travail_toc_contracts') ?></a>
|
||||
<a href="#rights"><?php echo t('travail_toc_rights') ?></a>
|
||||
<a href="#dismiss"><?php echo t('travail_toc_dismiss') ?></a>
|
||||
<a href="#unemployment"><?php echo t('travail_toc_unemployment') ?></a>
|
||||
</div>
|
||||
|
||||
<h2 id="cv"><?= t('travail_h2_cv') ?></h2>
|
||||
<p><?= t('travail_p_cv') ?></p>
|
||||
<h2 id="cv"><?php echo t('travail_h2_cv') ?></h2>
|
||||
<p><?php echo t('travail_p_cv') ?></p>
|
||||
|
||||
<h2 id="contracts"><?= t('travail_h2_contracts') ?></h2>
|
||||
<p><?= t('travail_p_contracts') ?></p>
|
||||
<h2 id="contracts"><?php echo t('travail_h2_contracts') ?></h2>
|
||||
<p><?php echo t('travail_p_contracts') ?></p>
|
||||
|
||||
<h2 id="rights"><?= t('travail_h2_rights') ?></h2>
|
||||
<p><?= t('travail_p_rights') ?></p>
|
||||
<h2 id="rights"><?php echo t('travail_h2_rights') ?></h2>
|
||||
<p><?php echo t('travail_p_rights') ?></p>
|
||||
|
||||
<h2 id="dismiss"><?= t('travail_h2_dismiss') ?></h2>
|
||||
<p><?= t('travail_p_dismiss') ?></p>
|
||||
<h2 id="dismiss"><?php echo t('travail_h2_dismiss') ?></h2>
|
||||
<p><?php echo t('travail_p_dismiss') ?></p>
|
||||
|
||||
<h2 id="unemployment"><?= t('travail_h2_unemployment') ?></h2>
|
||||
<p><?= t('travail_p_unemployment') ?></p>
|
||||
<h2 id="unemployment"><?php echo t('travail_h2_unemployment') ?></h2>
|
||||
<p><?php echo t('travail_p_unemployment') ?></p>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?= t('travail_tip_strong') ?></strong> <?= t('travail_tip_text') ?>
|
||||
<strong><?php echo t('travail_tip_strong') ?></strong> <?php echo t('travail_tip_text') ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?= t('travail_btn_find') ?></a>
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?php echo t('travail_btn_find') ?></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= t('copyr') ?></p>
|
||||
<p><?php echo t('copyr') ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
+92
-72
@@ -1,63 +1,83 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
require_once __DIR__ . '/../public/includes/lang.php';
|
||||
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool {
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (!empty($_SESSION['user_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['client_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'client') return true;
|
||||
if (!empty($_SESSION['user_id']) && $role === 'praticien') return true;
|
||||
if (!empty($_SESSION['praticien_id'])) return true;
|
||||
if (!empty($_SESSION['reference_id']) && $role === 'praticien') return true;
|
||||
return false;
|
||||
}
|
||||
// ===== Helpers header (identiques à index.php) =====
|
||||
function is_client_logged_in(): bool
|
||||
{
|
||||
$role = $_SESSION['role'] ?? ($_SESSION['user_type'] ?? '');
|
||||
if (! empty($_SESSION['user_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
if (! empty($_SESSION['client_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'client') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['user_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
if (! empty($_SESSION['praticien_id'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
if (! empty($_SESSION['reference_id']) && $role === 'praticien') {
|
||||
return true;
|
||||
}
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// helper simple
|
||||
function t(string $key, string $fallback = ''): string {
|
||||
global $translations;
|
||||
return (string)($translations[$key] ?? $fallback);
|
||||
}
|
||||
function include_header_clean(string $absPath): void
|
||||
{
|
||||
global $translations, $lang;
|
||||
ob_start();
|
||||
include $absPath; // /public/includes/header.php
|
||||
$buf = ob_get_clean() ?: '';
|
||||
|
||||
// 0) DOCTYPE + <html>…</html>
|
||||
$buf = preg_replace('~<!doctype\s+html[^>]*>~i', '', $buf);
|
||||
$buf = preg_replace('~</?html\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 1) retirer <head>…</head> et <body> ouverts/fermés
|
||||
$buf = preg_replace('~<head\b[^>]*>.*?</head>~is', '', $buf);
|
||||
$buf = preg_replace('~</?body\b[^>]*>~i', '', $buf);
|
||||
|
||||
// 2) retirer les <link> CSS “globaux” pour éviter d’écraser la home
|
||||
$buf = preg_replace('~<link[^>]+href="[^"]*(bootstrap[^"]*\.css|mobil_style\.css|site_style\.css|fonts\.googleapis)[^"]*"[^>]*>~i', '', $buf);
|
||||
|
||||
// 3) retirer le <script> Bootstrap CDN (on le charge déjà en bas de la page)
|
||||
$buf = preg_replace('~<script[^>]+src="[^"]*bootstrap[^"]*bundle[^"]*\.js[^"]*"[^>]*>\s*</script>~i', '', $buf);
|
||||
|
||||
echo $buf; // garde <header> + tes scripts inline utiles
|
||||
}
|
||||
|
||||
// helper simple
|
||||
function t(string $key, string $fallback = ''): string
|
||||
{
|
||||
global $translations;
|
||||
return (string) ($translations[$key] ?? $fallback);
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="<?= htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<html lang="<?php echo htmlspecialchars($lang ?? 'ru', ENT_QUOTES) ?>">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title><?= htmlspecialchars(t('seo_taxes_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?= htmlspecialchars(t('seo_taxes_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?= htmlspecialchars(t('seo_taxes_keywords'), ENT_QUOTES) ?>">
|
||||
<title><?php echo htmlspecialchars(t('seo_taxes_title'), ENT_QUOTES) ?></title>
|
||||
<meta name="description" content="<?php echo htmlspecialchars(t('seo_taxes_desc'), ENT_QUOTES) ?>">
|
||||
<meta name="keywords" content="<?php echo htmlspecialchars(t('seo_taxes_keywords'), ENT_QUOTES) ?>">
|
||||
<meta name="author" content="Uslugi.fr">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?= asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?= asset('/includes/mobil_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/site_style.css') ?>">
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/custom_style.css') ?>"> <!-- ta home -->
|
||||
|
||||
<link rel="stylesheet" href="<?php echo asset('/includes/mobil_style.css') ?>">
|
||||
<style>
|
||||
.topic { --brand:#38378B; --mint:#06FFA8; --text:#111; --muted:#4b5563; --card:#fff; --border:#e5e7eb; }
|
||||
.topic { font-family: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif; color:var(--text); }
|
||||
@@ -76,7 +96,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
.faq dt{ font-weight:600; margin-top:10px; }
|
||||
.faq dd{ margin-left:0; color:var(--muted); }
|
||||
</style>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php';?>
|
||||
<?php include_once __DIR__ . '/../includes/tracking.php'; ?>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Header minimal (logo + actions) -->
|
||||
@@ -102,8 +122,8 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<nav class="d-flex align-items-center gap-2">
|
||||
<a class="btn-login" href="/connexion.php">
|
||||
<span class="d-sm-none"><?= t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?= t('ja_spec') ?></span>
|
||||
<span class="d-sm-none"><?php echo t('btn_se_connecter') ?></span>
|
||||
<span class="d-none d-sm-inline"><?php echo t('ja_spec') ?></span>
|
||||
</a>
|
||||
|
||||
<div class="dropdown">
|
||||
@@ -113,16 +133,16 @@ function t(string $key, string $fallback = ''): string {
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-auto-close="true"
|
||||
aria-expanded="false"
|
||||
aria-label="<?= htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
aria-label="<?php echo htmlspecialchars(t('aria_help_label'), ENT_QUOTES) ?>">
|
||||
?
|
||||
</button>
|
||||
|
||||
<!-- Menu compact -->
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow help-menu menu-panel">
|
||||
<li><a href="/how-it-work.php"><?= t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?= t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?= t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?= t('nam_pisat') ?></a></li>
|
||||
<li><a href="/how-it-work.php"><?php echo t('kak_rabotaet') ?></a></li>
|
||||
<li><a href="/about.php"><?php echo t('pro_nas') ?></a></li>
|
||||
<li><a href="/faq.php"><?php echo t('faq') ?></a></li>
|
||||
<li><a href="/contact.php"><?php echo t('nam_pisat') ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -134,38 +154,38 @@ function t(string $key, string $fallback = ''): string {
|
||||
<div class="wrap">
|
||||
<div class="card">
|
||||
|
||||
<h1><?= t('taxes_h1') ?></h1>
|
||||
<p><?= t('taxes_intro') ?></p>
|
||||
<h1><?php echo t('taxes_h1') ?></h1>
|
||||
<p><?php echo t('taxes_intro') ?></p>
|
||||
|
||||
<div class="toc">
|
||||
<a href="#decl"><?= t('taxes_toc_decl') ?></a>
|
||||
<a href="#cot"><?= t('taxes_toc_cot') ?></a>
|
||||
<a href="#ae"><?= t('taxes_toc_ae') ?></a>
|
||||
<a href="#tva"><?= t('taxes_toc_tva') ?></a>
|
||||
<a href="#help"><?= t('taxes_toc_help') ?></a>
|
||||
<a href="#decl"><?php echo t('taxes_toc_decl') ?></a>
|
||||
<a href="#cot"><?php echo t('taxes_toc_cot') ?></a>
|
||||
<a href="#ae"><?php echo t('taxes_toc_ae') ?></a>
|
||||
<a href="#tva"><?php echo t('taxes_toc_tva') ?></a>
|
||||
<a href="#help"><?php echo t('taxes_toc_help') ?></a>
|
||||
</div>
|
||||
|
||||
<h2 id="decl"><?= t('taxes_h2_decl') ?></h2>
|
||||
<p><?= t('taxes_p_decl') ?></p>
|
||||
<h2 id="decl"><?php echo t('taxes_h2_decl') ?></h2>
|
||||
<p><?php echo t('taxes_p_decl') ?></p>
|
||||
|
||||
<h2 id="cot"><?= t('taxes_h2_cot') ?></h2>
|
||||
<p><?= t('taxes_p_cot') ?></p>
|
||||
<h2 id="cot"><?php echo t('taxes_h2_cot') ?></h2>
|
||||
<p><?php echo t('taxes_p_cot') ?></p>
|
||||
|
||||
<h2 id="ae"><?= t('taxes_h2_ae') ?></h2>
|
||||
<p><?= t('taxes_p_ae') ?></p>
|
||||
<h2 id="ae"><?php echo t('taxes_h2_ae') ?></h2>
|
||||
<p><?php echo t('taxes_p_ae') ?></p>
|
||||
|
||||
<h2 id="tva"><?= t('taxes_h2_tva') ?></h2>
|
||||
<p><?= t('taxes_p_tva') ?></p>
|
||||
<h2 id="tva"><?php echo t('taxes_h2_tva') ?></h2>
|
||||
<p><?php echo t('taxes_p_tva') ?></p>
|
||||
|
||||
<h2 id="help"><?= t('taxes_h2_help') ?></h2>
|
||||
<p><?= t('taxes_p_help') ?></p>
|
||||
<h2 id="help"><?php echo t('taxes_h2_help') ?></h2>
|
||||
<p><?php echo t('taxes_p_help') ?></p>
|
||||
|
||||
<div class="callout">
|
||||
<strong><?= t('taxes_tip_strong') ?></strong> <?= t('taxes_tip_text') ?>
|
||||
<strong><?php echo t('taxes_tip_strong') ?></strong> <?php echo t('taxes_tip_text') ?>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?= t('taxes_btn_find') ?></a>
|
||||
<a class="btn btn-primary btn-index" href="/index.php"><?php echo t('taxes_btn_find') ?></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -174,7 +194,7 @@ function t(string $key, string $fallback = ''): string {
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p><?= t('copyr') ?></p>
|
||||
<p><?php echo t('copyr') ?></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
Reference in new issue
Block a user