Files

522 lines
19 KiB
PHP

<?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>