feat: add landing page templates and registration modal
- Implemented header and hero section in _header.html.twig and _hero_art.html.twig. - Created a pre-registration modal in _reg_modal.html.twig with form fields and validation. - Added page scripts for dynamic behavior and interaction in _page_scripts.html.twig. - Developed landing page structure in landing.html.twig, integrating header, footer, and modal. - Introduced tests for landing page rendering and registry validation in LandingPageTest.php and LandingRegistryTest.php.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
<!-- ===================== Footer ===================== -->
|
||||
<footer class="site-footer" id="contact">
|
||||
<div class="wrap">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-col footer-brand">
|
||||
<a class="brand" href="#hero">
|
||||
<b>کلینیک پرو</b>
|
||||
<span class="dot"></span>
|
||||
</a>
|
||||
<p>کلینیک پرو را ساختیم تا پزشکها بهجای درگیری با دفتر و کاغذ، حواسشان به کار اصلیشان باشد: بیمار.</p>
|
||||
<div class="foot-socials">
|
||||
<a href="#" aria-label="اینستاگرام">
|
||||
<svg viewbox="0 0 24 24" fill="none"><rect x="3" y="3" width="18" height="18" rx="5" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.8"/><circle cx="17.4" cy="6.6" r="1.2" fill="currentColor"/></svg>
|
||||
</a>
|
||||
<a href="#" aria-label="تلگرام">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M21 4 3 11l5 2 2 6 3-4 5 4 3-15Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
<a href="#" aria-label="واتساپ">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M4 20l1.4-4A8 8 0 1 1 9 18.6L4 20Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<!-- نماد اعتماد الکترونیکی — بعد از لود کامل صفحه تزریق میشود (footer JS) -->
|
||||
<div id="enamad-seal" style="margin-top:18px"></div>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4>دسترسی سریع</h4>
|
||||
<div class="foot-links">
|
||||
<a href="#features">امکانات</a>
|
||||
<a href="#why">چرا کلینیک پرو</a>
|
||||
<a href="#download" style="display:none">دانلود نرمافزار</a>
|
||||
<a href="#contact">تماس با ما</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4>راهکارها</h4>
|
||||
<div class="foot-links">
|
||||
{% for landing in landing_pages.all() %}
|
||||
<a href="/{{ landing.slug }}">{{ landing.h1 }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4>اطلاعات تماس</h4>
|
||||
<div class="foot-contact">
|
||||
<div class="fl">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M12 21s-7-5.2-7-11a7 7 0 0 1 14 0c0 5.8-7 11-7 11Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><circle cx="12" cy="10" r="2.6" stroke="currentColor" stroke-width="1.7"/></svg>
|
||||
<span>یاسوج، مهریان، خیابان شهید ستاره شیرازی، خیابان امامزاده احمد، پلاک ۸ شرکت توسعه فناوری اطلاعات حامی</span>
|
||||
</div>
|
||||
<div class="fl">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M4 6.5C4 5 5 4 6.5 4h2c.6 0 1.1.4 1.3 1l1 3c.2.6 0 1.2-.5 1.6L9 11c1 2 2.5 3.5 4.5 4.5l1.4-1.3c.4-.4 1-.6 1.6-.4l3 1c.6.2 1 .7 1 1.3v2c0 1.5-1 2.5-2.5 2.4C10.5 20 4 13.5 4 6.5Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
<a href="tel:02191550875" style="font-variant-numeric:tabular-nums" dir="ltr">02191550875</a>
|
||||
|
||||
</div>
|
||||
<div class="fl">
|
||||
<svg viewbox="0 0 24 24" fill="none"><rect x="3" y="5" width="18" height="14" rx="2" stroke="currentColor" stroke-width="1.7"/><path d="m4 7 8 5 8-5" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
<a href="mailto:info@clinic-pro.ir" class="mono" dir="ltr">info@clinic-pro.ir</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-col" style="display:none">
|
||||
<h4>دانلود نرمافزار</h4>
|
||||
<div class="foot-badges">
|
||||
<a class="store-badge" href="#" style="background:oklch(1 0 0 / 0.08)">
|
||||
<svg viewbox="0 0 24 24" fill="currentColor"><path d="M16.4 12.6c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.9-3.5.9-.7 0-1.8-.8-3-.8-1.5 0-3 .9-3.7 2.3-1.6 2.8-.4 6.9 1.1 9.2.8 1.1 1.6 2.3 2.8 2.3 1.1 0 1.6-.7 2.9-.7 1.4 0 1.7.7 2.9.7 1.2 0 2-1.1 2.7-2.2.9-1.2 1.2-2.5 1.2-2.5s-2.3-.9-2.3-3.6ZM14.2 5.7c.6-.8 1-1.8.9-2.9-.9 0-2 .6-2.6 1.4-.6.7-1.1 1.7-.9 2.7 1 .1 2-.5 2.6-1.2Z"/></svg>
|
||||
<span class="sb-t">
|
||||
<small>دانلود برای</small>
|
||||
<b>مک · macOS</b>
|
||||
</span>
|
||||
</a>
|
||||
<a class="store-badge" href="#" style="background:oklch(1 0 0 / 0.08)">
|
||||
<svg viewbox="0 0 24 24" fill="currentColor"><path d="M3 5.5 10.5 4.4v7.1H3V5.5Zm0 13L10.5 19.6v-7H3v6Zm8.5 1.3L21 21V12.5h-9.5v7.3Zm0-15.6V11.5H21V3l-9.5 1.2Z"/></svg>
|
||||
<span class="sb-t">
|
||||
<small>دانلود برای</small>
|
||||
<b>ویندوز</b>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">© ۲۰۲۴ کلینیک پرو · ساختهشده برای پزشکان ایران</div>
|
||||
</footer>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!-- ===================== Header ===================== -->
|
||||
<header class="site-header" id="header">
|
||||
<div class="wrap nav">
|
||||
<a class="brand" href="#hero" aria-label="کلینیک پرو">
|
||||
<b>کلینیک پرو</b>
|
||||
<span class="dot"></span>
|
||||
<small>مدیریت مطب</small>
|
||||
</a>
|
||||
|
||||
<nav class="nav-links" id="navLinks">
|
||||
<a href="#hero" class="active">خانه</a>
|
||||
<a href="#features">امکانات</a>
|
||||
<a href="#why">چرا کلینیک پرو</a>
|
||||
<a href="#download" style="display:none">دانلود</a>
|
||||
<a href="#contact">تماس با ما</a>
|
||||
<a href="#" id="openRegModalNav" class="nav-reg-mobile">ثبت نام</a>
|
||||
</nav>
|
||||
|
||||
<div class="nav-right">
|
||||
<button class="nav-burger nav-toggle" id="navToggle" aria-label="منو">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||||
</button>
|
||||
<button class="btn btn-ghost" id="openRegModal" style="font-size:13px;padding:8px 20px">ثبت نام</button>
|
||||
<a href="/admin" class="btn btn-blue" style="font-size:13px;padding:8px 20px;text-decoration:none">ورود به پنل</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,80 @@
|
||||
<div class="hero-art reveal d1">
|
||||
<div class="art-chip chip-1">
|
||||
<span class="ci">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M12 21s-7-4.3-7-9.5A4 4 0 0 1 12 8a4 4 0 0 1 7 3.5C19 16.7 12 21 12 21Z" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<b style="font-variant-numeric:tabular-nums">۹۵٪</b>
|
||||
<span>رضایت بیماران</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="art-chip chip-2">
|
||||
<span class="ci">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M8 7V5m8 2V5M4 9h16M5 7h14v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7Z" stroke="currentColor" stroke-width="1.9"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<b style="font-variant-numeric:tabular-nums">۳۸</b>
|
||||
<span>نوبت امروز</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svg viewbox="0 0 600 480" role="img" aria-label="تصویر مدیریت مطب">
|
||||
<ellipse cx="300" cy="438" rx="250" ry="30" fill="#e2e9fb"/>
|
||||
<circle cx="300" cy="244" r="184" fill="#eaeffb"/>
|
||||
<g fill="#dbe4fb"><ellipse cx="138" cy="150" rx="42" ry="20"/><ellipse cx="476" cy="120" rx="48" ry="22"/><ellipse cx="508" cy="250" rx="30" ry="15"/></g>
|
||||
|
||||
<rect x="196" y="184" width="208" height="152" rx="13" fill="#fff" stroke="#dde3f7" stroke-width="3"/>
|
||||
<rect x="210" y="198" width="180" height="124" rx="7" fill="#eef2fd"/>
|
||||
<rect x="223" y="211" width="68" height="9" rx="4.5" fill="#c4cef2"/>
|
||||
<circle cx="378" cy="216" r="6" fill="#f8b3a6"/>
|
||||
<path d="M223 272 h24 l9 -22 12 40 10 -28 8 14 h62" fill="none" stroke="#5666e0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g fill="#cdd6f4"><rect x="226" y="292" width="14" height="22" rx="3"/><rect x="246" y="284" width="14" height="30" rx="3"/><rect x="266" y="298" width="14" height="16" rx="3"/></g>
|
||||
<rect x="330" y="288" width="50" height="26" rx="6" fill="#fde3df"/>
|
||||
<path d="M166 336 h268 l26 28 H140 z" fill="#cfd9f9"/>
|
||||
<path d="M166 336 h268 l6 6 H160 z" fill="#aab6ee"/>
|
||||
<rect x="268" y="350" width="64" height="6" rx="3" fill="#9aa8ea"/>
|
||||
|
||||
<g fill="#fff"><ellipse cx="300" cy="190" rx="58" ry="22"/><ellipse cx="258" cy="196" rx="26" ry="15"/><ellipse cx="342" cy="196" rx="26" ry="15"/></g>
|
||||
|
||||
<path d="M276 150 q-20 16 -15 42 l19 -11 z" fill="#3a3a7d"/>
|
||||
<path d="M324 150 q20 16 15 42 l-19 -11 z" fill="#3a3a7d"/>
|
||||
<rect x="278" y="70" width="44" height="118" rx="22" fill="#fff" stroke="#dfe4f7" stroke-width="2"/>
|
||||
<path d="M300 50 a22 22 0 0 1 22 26 h-44 a22 22 0 0 1 22 -26z" fill="#f17a6b"/>
|
||||
<circle cx="300" cy="106" r="13" fill="#cfe0fb" stroke="#5666e0" stroke-width="3"/>
|
||||
<g fill="#5666e0"><rect x="295" y="130" width="10" height="30" rx="3"/><rect x="285" y="140" width="30" height="10" rx="3"/></g>
|
||||
<path d="M289 188 q11 24 11 30 q0 -6 11 -30 z" fill="#f8b3a6"/>
|
||||
<g stroke="#bcc7f2" stroke-width="4" stroke-linecap="round"><path d="M250 92 h-20"/><path d="M258 112 h-13"/><path d="M350 92 h20"/><path d="M342 112 h13"/></g>
|
||||
|
||||
<g>
|
||||
<path d="M86 332 h36 l-2 86 a6 6 0 0 1 -12 0 l-4 -52 -4 52 a6 6 0 0 1 -12 0 z" fill="#3a3a7d"/>
|
||||
<ellipse cx="90" cy="420" rx="12" ry="6" fill="#2b2b5e"/>
|
||||
<ellipse cx="118" cy="420" rx="12" ry="6" fill="#2b2b5e"/>
|
||||
<path d="M80 262 q-14 30 -6 58" fill="none" stroke="#fff" stroke-width="15" stroke-linecap="round"/>
|
||||
<circle cx="76" cy="318" r="7" fill="#f3c6a5"/>
|
||||
<path d="M78 256 q26 -18 54 0 l8 80 h-70 z" fill="#fff" stroke="#dde3f7" stroke-width="2"/>
|
||||
<path d="M105 250 l-9 56 9 7 9 -7 -9 -56z" fill="#eef2fd"/>
|
||||
<path d="M99 254 q-12 28 9 42" fill="none" stroke="#5666e0" stroke-width="2.6"/>
|
||||
<circle cx="110" cy="298" r="5" fill="#5666e0"/>
|
||||
<path d="M128 260 q42 -6 66 -54" fill="none" stroke="#fff" stroke-width="15" stroke-linecap="round"/>
|
||||
<circle cx="196" cy="206" r="7.5" fill="#f3c6a5"/>
|
||||
<rect x="99" y="232" width="12" height="16" rx="4" fill="#e8b594"/>
|
||||
<circle cx="105" cy="218" r="22" fill="#f3c6a5"/>
|
||||
<path d="M83 216 q0 -30 31 -28 q19 1 21 22 q-13 -12 -30 -7 q-15 4 -22 13z" fill="#3a3a7d"/>
|
||||
</g>
|
||||
|
||||
<g>
|
||||
<path d="M478 332 h36 l-2 86 a6 6 0 0 1 -12 0 l-4 -52 -4 52 a6 6 0 0 1 -12 0 z" fill="#4f51a8"/>
|
||||
<ellipse cx="482" cy="420" rx="12" ry="6" fill="#34356f"/>
|
||||
<ellipse cx="510" cy="420" rx="12" ry="6" fill="#34356f"/>
|
||||
<path d="M512 258 q26 -16 30 -54" fill="none" stroke="#fff" stroke-width="15" stroke-linecap="round"/>
|
||||
<circle cx="543" cy="200" r="8" fill="#f3c6a5"/>
|
||||
<path d="M462 256 q26 -18 54 0 l6 80 h-66 z" fill="#fff" stroke="#dde3f7" stroke-width="2"/>
|
||||
<path d="M489 250 l-8 56 8 7 8 -7 -8 -56z" fill="#fde3df"/>
|
||||
<path d="M464 260 q-12 28 -6 54" fill="none" stroke="#fff" stroke-width="14" stroke-linecap="round"/>
|
||||
<circle cx="460" cy="316" r="7" fill="#f3c6a5"/>
|
||||
<rect x="483" y="232" width="12" height="16" rx="4" fill="#e8b594"/>
|
||||
<circle cx="489" cy="218" r="22" fill="#f3c6a5"/>
|
||||
<path d="M467 220 q-4 -32 28 -32 q24 0 22 30 q-2 14 -6 20 q4 -22 -8 -30 q4 12 -2 18 q-10 -20 -34 -6z" fill="#3a3a7d"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
@@ -0,0 +1,166 @@
|
||||
<script>
|
||||
(function () {
|
||||
'use strict';
|
||||
var FA = [
|
||||
'۰',
|
||||
'۱',
|
||||
'۲',
|
||||
'۳',
|
||||
'۴',
|
||||
'۵',
|
||||
'۶',
|
||||
'۷',
|
||||
'۸',
|
||||
'۹'
|
||||
];
|
||||
function groupFa(n) {
|
||||
return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, '،').replace(/\d/g, function (d) {
|
||||
return FA[+ d];
|
||||
});
|
||||
}
|
||||
|
||||
var header = document.getElementById('header');
|
||||
function onScroll() {
|
||||
header.classList.toggle('scrolled', window.scrollY > 12);
|
||||
}
|
||||
window.addEventListener('scroll', onScroll, {passive: true});
|
||||
onScroll();
|
||||
|
||||
var navToggle = document.getElementById('navToggle');
|
||||
var navLinks = document.getElementById('navLinks');
|
||||
if (navToggle) {
|
||||
navToggle.addEventListener('click', function () {
|
||||
navLinks.classList.toggle('open');
|
||||
});
|
||||
navLinks.addEventListener('click', function (e) {
|
||||
if (e.target.tagName === 'A')
|
||||
navLinks.classList.remove('open');
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var sections = [
|
||||
'hero',
|
||||
'features',
|
||||
'why',
|
||||
'download',
|
||||
'contact'
|
||||
];
|
||||
var links = Array.prototype.slice.call(document.querySelectorAll('.nav-links a'));
|
||||
function syncActive() {
|
||||
var y = window.scrollY + 120,
|
||||
cur = 'hero';
|
||||
sections.forEach(function (id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el && el.offsetTop <= y)
|
||||
cur = id;
|
||||
|
||||
|
||||
|
||||
});
|
||||
links.forEach(function (a) {
|
||||
a.classList.toggle('active', a.getAttribute('href') === '#' + cur);
|
||||
});
|
||||
}
|
||||
window.addEventListener('scroll', syncActive, {passive: true});
|
||||
syncActive();
|
||||
|
||||
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
var reveals = Array.prototype.slice.call(document.querySelectorAll('.reveal'));
|
||||
function inView(el) {
|
||||
var r = el.getBoundingClientRect();
|
||||
return r.top<(window.innerHeight||document.documentElement.clientHeight)-30 && r.bottom> 0;
|
||||
}
|
||||
function reveal(el) {
|
||||
el.classList.add('in');
|
||||
}
|
||||
|
||||
if (reduce) {
|
||||
reveals.forEach(reveal);
|
||||
} else {
|
||||
reveals.forEach(function (el) {
|
||||
if (inView(el))
|
||||
reveal(el);
|
||||
|
||||
|
||||
|
||||
});
|
||||
if ('IntersectionObserver' in window) {
|
||||
var io = new IntersectionObserver(function (es) {
|
||||
es.forEach(function (e) {
|
||||
if (e.isIntersecting) {
|
||||
reveal(e.target);
|
||||
io.unobserve(e.target);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
threshold: 0.12,
|
||||
rootMargin: '0px 0px -40px 0px'
|
||||
});
|
||||
reveals.forEach(function (el) {
|
||||
if (! el.classList.contains('in'))
|
||||
io.observe(el);
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
var ticking = false;
|
||||
function sweep() {
|
||||
if (ticking)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
reveals.forEach(function (el) {
|
||||
if (inView(el))
|
||||
reveal(el);
|
||||
|
||||
|
||||
|
||||
});
|
||||
ticking = false;
|
||||
});
|
||||
}
|
||||
window.addEventListener('scroll', sweep, {passive: true});
|
||||
window.addEventListener('resize', sweep, {passive: true});
|
||||
setTimeout(function () {
|
||||
reveals.forEach(reveal);
|
||||
}, 2800);
|
||||
}
|
||||
|
||||
// نماد اعتماد الکترونیکی (Enamad) — فقط بعد از لود کامل صفحه تزریق میشود تا
|
||||
// درخواست تصویرِ دامنهی بیرونی با منابع خود سایت رقابت نکند و سرعت لود پایین نیاید.
|
||||
function mountEnamad() {
|
||||
var slot = document.getElementById('enamad-seal');
|
||||
if (! slot)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.setAttribute('referrerpolicy', 'origin');
|
||||
a.target = '_blank';
|
||||
a.href = 'https://trustseal.enamad.ir/?id=755841&Code=8sNSk0yrUE7EgbY9k5xkqTE0LaeXIaq4';
|
||||
var img = document.createElement('img');
|
||||
img.setAttribute('referrerpolicy', 'origin');
|
||||
img.src = 'https://trustseal.enamad.ir/logo.aspx?id=755841&Code=8sNSk0yrUE7EgbY9k5xkqTE0LaeXIaq4';
|
||||
img.alt = 'نماد اعتماد الکترونیکی';
|
||||
img.style.cursor = 'pointer';
|
||||
img.setAttribute('code', '8sNSk0yrUE7EgbY9k5xkqTE0LaeXIaq4');
|
||||
img.loading = 'lazy';
|
||||
a.appendChild(img);
|
||||
slot.appendChild(a);
|
||||
}
|
||||
if (document.readyState === 'complete') {
|
||||
mountEnamad();
|
||||
} else {
|
||||
window.addEventListener('load', mountEnamad);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,240 @@
|
||||
<!-- ===================== Pre-Registration Modal ===================== -->
|
||||
<div id="regOverlay" style="display:none;position:fixed;inset:0;background:oklch(0.2 0.05 285 / 0.55);z-index:900;backdrop-filter:blur(4px);overflow-y:auto;padding:24px 16px" onclick="if(event.target===this)closeRegModal()">
|
||||
<div style="background:#fff;border-radius:20px;max-width:520px;margin:auto;padding:32px 28px;position:relative;box-shadow:0 24px 60px oklch(0.3 0.1 285 / 0.22)">
|
||||
<button onclick="closeRegModal()" aria-label="بستن" style="position:absolute;top:16px;left:20px;background:none;border:none;cursor:pointer;font-size:22px;color:var(--text-2);line-height:1">×</button>
|
||||
|
||||
<h2 style="margin:0 0 6px;font-size:20px;font-weight:800;color:var(--ink)">ثبت نام در کلینیک پرو</h2>
|
||||
<p style="margin:0 0 24px;font-size:13px;color:var(--text-2)">نوع حساب خود را انتخاب کنید</p>
|
||||
|
||||
<!-- Type Cards -->
|
||||
<div id="typeCards" style="display:flex;flex-direction:column;gap:10px;margin-bottom:22px">
|
||||
|
||||
<label class="reg-card" data-type="independent_doctor" style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid var(--border);border-radius:14px;cursor:pointer;transition:all .2s">
|
||||
<input type="radio" name="regType" value="independent_doctor" style="display:none">
|
||||
<span style="font-size:26px;flex-shrink:0">🩺</span>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px;color:var(--ink)">دکتر هستم</div>
|
||||
<div style="font-size:12px;color:var(--text-2);margin-top:2px">مطب شخصی دارم، به تنهایی کار میکنم</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="reg-card" data-type="doctor_with_clinic" style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid var(--border);border-radius:14px;cursor:pointer;transition:all .2s">
|
||||
<input type="radio" name="regType" value="doctor_with_clinic" style="display:none">
|
||||
<span style="font-size:26px;flex-shrink:0">🏥</span>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px;color:var(--ink)">دکتر هستم و کلینیک دارم</div>
|
||||
<div style="font-size:12px;color:var(--text-2);margin-top:2px">با چند دکتر در یک کلینیک همکاری میکنم</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="reg-card" data-type="clinic_manager" style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid var(--border);border-radius:14px;cursor:pointer;transition:all .2s">
|
||||
<input type="radio" name="regType" value="clinic_manager" style="display:none">
|
||||
<span style="font-size:26px;flex-shrink:0">🏢</span>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px;color:var(--ink)">مدیر کلینیک هستم</div>
|
||||
<div style="font-size:12px;color:var(--text-2);margin-top:2px">مدیریت کلینیک را دارم، خودم دکتر نیستم</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Form Fields -->
|
||||
<div id="regFields" style="display:flex;flex-direction:column;gap:14px">
|
||||
<div>
|
||||
<label style="display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink)">نام کامل
|
||||
<span style="color:var(--coral)">*</span>
|
||||
</label>
|
||||
<input id="regName" type="text" placeholder="مثال: دکتر علی احمدی" style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;color:var(--ink)"/>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink)">شماره موبایل
|
||||
<span style="color:var(--coral)">*</span>
|
||||
</label>
|
||||
<input id="regMobile" type="tel" placeholder="09xxxxxxxxx" dir="ltr" style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;color:var(--ink);text-align:right"/>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink)">توضیحات
|
||||
<span style="font-weight:400;color:var(--text-2)">(اختیاری)</span>
|
||||
</label>
|
||||
<textarea id="regInfo" rows="3" placeholder="تخصص، آدرس، سابقه کاری، ..." style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;resize:vertical;color:var(--ink)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if altcha_enabled %}
|
||||
<!-- ALTCHA captcha — proof-of-work در پسزمینه (بدون تعامل کاربر) -->
|
||||
{# widget v3: attribute «challenge» (نه challengeurl قدیمی) #}
|
||||
<altcha-widget id="regAltcha" challenge="/api/v1/altcha/challenge" auto="onload" language="fa" style="display:block;margin-top:16px"></altcha-widget>
|
||||
{% endif %}
|
||||
|
||||
<!-- Error / Success -->
|
||||
<div id="regMsg" style="display:none;margin-top:14px;padding:12px 16px;border-radius:10px;font-size:13px"></div>
|
||||
|
||||
<button id="regSubmitBtn" disabled onclick="submitReg()" style="margin-top:20px;width:100%;background:var(--blue);color:#fff;border:none;border-radius:12px;padding:13px;font-size:15px;font-weight:700;cursor:pointer;font-family:inherit;opacity:.45;transition:opacity .2s">
|
||||
ارسال درخواست
|
||||
</button>
|
||||
<p style="text-align:center;font-size:12px;color:var(--text-2);margin:12px 0 0">پس از بررسی، اطلاعات ورود از طریق SMS ارسال میشود</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.reg-card:hover {
|
||||
border-color: var(--blue) !important;
|
||||
background: oklch(0.97 0.02 277);
|
||||
}
|
||||
.reg-card.selected {
|
||||
border-color: var(--blue) !important;
|
||||
background: oklch(0.96 0.03 277);
|
||||
}
|
||||
.reg-card.selected div > div:first-child {
|
||||
color: var(--blue);
|
||||
}
|
||||
#regName:focus,
|
||||
#regMobile:focus,
|
||||
#regInfo:focus {
|
||||
border-color: var(--blue);
|
||||
box-shadow: 0 0 0 3px oklch(0.58 0.185 277 / 0.12);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var overlay = document.getElementById('regOverlay');
|
||||
var submitBtn = document.getElementById('regSubmitBtn');
|
||||
var selectedType = null;
|
||||
|
||||
// payload حلشدهی ALTCHA (یکبارمصرف؛ در prod الزامی است)
|
||||
var regAltchaPayload = '';
|
||||
var regAltchaEl = document.getElementById('regAltcha');
|
||||
if (regAltchaEl)
|
||||
regAltchaEl.addEventListener('statechange', function (e) {
|
||||
if (e.detail && e.detail.state === 'verified')
|
||||
regAltchaPayload = e.detail.payload;
|
||||
});
|
||||
|
||||
function openRegModal() {
|
||||
overlay.style.display = 'block';
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
window.closeRegModal = function () {
|
||||
overlay.style.display = 'none';
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
var btn1 = document.getElementById('openRegModal');
|
||||
var btn2 = document.getElementById('openRegModal2');
|
||||
var btn3 = document.getElementById('openRegModalNav');
|
||||
if (btn1)
|
||||
btn1.addEventListener('click', openRegModal);
|
||||
|
||||
|
||||
|
||||
if (btn2)
|
||||
btn2.addEventListener('click', openRegModal);
|
||||
|
||||
|
||||
|
||||
if (btn3)
|
||||
btn3.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
openRegModal();
|
||||
});
|
||||
|
||||
|
||||
|
||||
document.querySelectorAll('.reg-card').forEach(function (card) {
|
||||
card.addEventListener('click', function () {
|
||||
document.querySelectorAll('.reg-card').forEach(function (c) {
|
||||
c.classList.remove('selected');
|
||||
});
|
||||
card.classList.add('selected');
|
||||
var radio = card.querySelector('input[type=radio]');
|
||||
if (radio)
|
||||
radio.checked = true;
|
||||
|
||||
|
||||
|
||||
selectedType = card.dataset.type;
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.style.opacity = '1';
|
||||
});
|
||||
});
|
||||
|
||||
window.submitReg = function () {
|
||||
var name = document.getElementById('regName').value.trim();
|
||||
var mobile = document.getElementById('regMobile').value.trim();
|
||||
var info = document.getElementById('regInfo').value.trim();
|
||||
var msg = document.getElementById('regMsg');
|
||||
|
||||
if (! selectedType)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
if (! name) {
|
||||
showMsg('نام را وارد کنید', 'error');
|
||||
return;
|
||||
}
|
||||
if (! mobile || mobile.length < 10) {
|
||||
showMsg('شماره موبایل معتبر نیست', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = 'در حال ارسال...';
|
||||
|
||||
fetch('/api/v1/pre-registration', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(
|
||||
{
|
||||
type: selectedType,
|
||||
name: name,
|
||||
mobile: mobile,
|
||||
info: info || null,
|
||||
altcha: regAltchaPayload
|
||||
}
|
||||
)
|
||||
}).then(function (r) {
|
||||
return r.json();
|
||||
}).then(function (data) {
|
||||
if (data.success) {
|
||||
showMsg('درخواست شما ثبت شد. پس از بررسی، اطلاعات ورود از طریق SMS ارسال میشود.', 'success');
|
||||
submitBtn.textContent = 'ارسال شد ✓';
|
||||
setTimeout(function () {
|
||||
closeRegModal();
|
||||
}, 2200);
|
||||
} else {
|
||||
var errMsg = (data.errors && data.errors[0]) ? data.errors[0].message : 'خطایی رخ داد';
|
||||
showMsg(errMsg, 'error');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.style.opacity = '1';
|
||||
submitBtn.textContent = 'ارسال درخواست';
|
||||
resetRegAltcha();
|
||||
}
|
||||
}).catch(function () {
|
||||
showMsg('خطا در اتصال به سرور', 'error');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.style.opacity = '1';
|
||||
submitBtn.textContent = 'ارسال درخواست';
|
||||
resetRegAltcha();
|
||||
});
|
||||
};
|
||||
|
||||
// challenge یکبارمصرف است؛ بعد از خطا یک challenge تازه بگیر.
|
||||
function resetRegAltcha() {
|
||||
regAltchaPayload = '';
|
||||
if (regAltchaEl && typeof regAltchaEl.reset === 'function')
|
||||
regAltchaEl.reset();
|
||||
}
|
||||
|
||||
function showMsg(text, type) {
|
||||
var msg = document.getElementById('regMsg');
|
||||
msg.textContent = text;
|
||||
msg.style.display = 'block';
|
||||
msg.style.background = type === 'success' ? '#dcfce7' : '#fef2f2';
|
||||
msg.style.color = type === 'success' ? '#16a34a' : '#ef4444';
|
||||
msg.style.border = type === 'success' ? '1px solid #bbf7d0' : '1px solid #fecaca';
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -70,33 +70,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ===================== Header ===================== -->
|
||||
<header class="site-header" id="header">
|
||||
<div class="wrap nav">
|
||||
<a class="brand" href="#hero" aria-label="کلینیک پرو">
|
||||
<b>کلینیک پرو</b>
|
||||
<span class="dot"></span>
|
||||
<small>مدیریت مطب</small>
|
||||
</a>
|
||||
|
||||
<nav class="nav-links" id="navLinks">
|
||||
<a href="#hero" class="active">خانه</a>
|
||||
<a href="#features">امکانات</a>
|
||||
<a href="#why">چرا کلینیک پرو</a>
|
||||
<a href="#download" style="display:none">دانلود</a>
|
||||
<a href="#contact">تماس با ما</a>
|
||||
<a href="#" id="openRegModalNav" class="nav-reg-mobile">ثبت نام</a>
|
||||
</nav>
|
||||
|
||||
<div class="nav-right">
|
||||
<button class="nav-burger nav-toggle" id="navToggle" aria-label="منو">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||||
</button>
|
||||
<button class="btn btn-ghost" id="openRegModal" style="font-size:13px;padding:8px 20px">ثبت نام</button>
|
||||
<a href="/admin" class="btn btn-blue" style="font-size:13px;padding:8px 20px;text-decoration:none">ورود به پنل</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{{ include('public/_header.html.twig') }}
|
||||
|
||||
<main>
|
||||
<!-- ===================== Hero ===================== -->
|
||||
@@ -111,86 +85,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-art reveal d1">
|
||||
<div class="art-chip chip-1">
|
||||
<span class="ci">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M12 21s-7-4.3-7-9.5A4 4 0 0 1 12 8a4 4 0 0 1 7 3.5C19 16.7 12 21 12 21Z" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<b style="font-variant-numeric:tabular-nums">۹۵٪</b>
|
||||
<span>رضایت بیماران</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="art-chip chip-2">
|
||||
<span class="ci">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M8 7V5m8 2V5M4 9h16M5 7h14v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V7Z" stroke="currentColor" stroke-width="1.9"/></svg>
|
||||
</span>
|
||||
<div>
|
||||
<b style="font-variant-numeric:tabular-nums">۳۸</b>
|
||||
<span>نوبت امروز</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svg viewbox="0 0 600 480" role="img" aria-label="تصویر مدیریت مطب">
|
||||
<ellipse cx="300" cy="438" rx="250" ry="30" fill="#e2e9fb"/>
|
||||
<circle cx="300" cy="244" r="184" fill="#eaeffb"/>
|
||||
<g fill="#dbe4fb"><ellipse cx="138" cy="150" rx="42" ry="20"/><ellipse cx="476" cy="120" rx="48" ry="22"/><ellipse cx="508" cy="250" rx="30" ry="15"/></g>
|
||||
|
||||
<rect x="196" y="184" width="208" height="152" rx="13" fill="#fff" stroke="#dde3f7" stroke-width="3"/>
|
||||
<rect x="210" y="198" width="180" height="124" rx="7" fill="#eef2fd"/>
|
||||
<rect x="223" y="211" width="68" height="9" rx="4.5" fill="#c4cef2"/>
|
||||
<circle cx="378" cy="216" r="6" fill="#f8b3a6"/>
|
||||
<path d="M223 272 h24 l9 -22 12 40 10 -28 8 14 h62" fill="none" stroke="#5666e0" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g fill="#cdd6f4"><rect x="226" y="292" width="14" height="22" rx="3"/><rect x="246" y="284" width="14" height="30" rx="3"/><rect x="266" y="298" width="14" height="16" rx="3"/></g>
|
||||
<rect x="330" y="288" width="50" height="26" rx="6" fill="#fde3df"/>
|
||||
<path d="M166 336 h268 l26 28 H140 z" fill="#cfd9f9"/>
|
||||
<path d="M166 336 h268 l6 6 H160 z" fill="#aab6ee"/>
|
||||
<rect x="268" y="350" width="64" height="6" rx="3" fill="#9aa8ea"/>
|
||||
|
||||
<g fill="#fff"><ellipse cx="300" cy="190" rx="58" ry="22"/><ellipse cx="258" cy="196" rx="26" ry="15"/><ellipse cx="342" cy="196" rx="26" ry="15"/></g>
|
||||
|
||||
<path d="M276 150 q-20 16 -15 42 l19 -11 z" fill="#3a3a7d"/>
|
||||
<path d="M324 150 q20 16 15 42 l-19 -11 z" fill="#3a3a7d"/>
|
||||
<rect x="278" y="70" width="44" height="118" rx="22" fill="#fff" stroke="#dfe4f7" stroke-width="2"/>
|
||||
<path d="M300 50 a22 22 0 0 1 22 26 h-44 a22 22 0 0 1 22 -26z" fill="#f17a6b"/>
|
||||
<circle cx="300" cy="106" r="13" fill="#cfe0fb" stroke="#5666e0" stroke-width="3"/>
|
||||
<g fill="#5666e0"><rect x="295" y="130" width="10" height="30" rx="3"/><rect x="285" y="140" width="30" height="10" rx="3"/></g>
|
||||
<path d="M289 188 q11 24 11 30 q0 -6 11 -30 z" fill="#f8b3a6"/>
|
||||
<g stroke="#bcc7f2" stroke-width="4" stroke-linecap="round"><path d="M250 92 h-20"/><path d="M258 112 h-13"/><path d="M350 92 h20"/><path d="M342 112 h13"/></g>
|
||||
|
||||
<g>
|
||||
<path d="M86 332 h36 l-2 86 a6 6 0 0 1 -12 0 l-4 -52 -4 52 a6 6 0 0 1 -12 0 z" fill="#3a3a7d"/>
|
||||
<ellipse cx="90" cy="420" rx="12" ry="6" fill="#2b2b5e"/>
|
||||
<ellipse cx="118" cy="420" rx="12" ry="6" fill="#2b2b5e"/>
|
||||
<path d="M80 262 q-14 30 -6 58" fill="none" stroke="#fff" stroke-width="15" stroke-linecap="round"/>
|
||||
<circle cx="76" cy="318" r="7" fill="#f3c6a5"/>
|
||||
<path d="M78 256 q26 -18 54 0 l8 80 h-70 z" fill="#fff" stroke="#dde3f7" stroke-width="2"/>
|
||||
<path d="M105 250 l-9 56 9 7 9 -7 -9 -56z" fill="#eef2fd"/>
|
||||
<path d="M99 254 q-12 28 9 42" fill="none" stroke="#5666e0" stroke-width="2.6"/>
|
||||
<circle cx="110" cy="298" r="5" fill="#5666e0"/>
|
||||
<path d="M128 260 q42 -6 66 -54" fill="none" stroke="#fff" stroke-width="15" stroke-linecap="round"/>
|
||||
<circle cx="196" cy="206" r="7.5" fill="#f3c6a5"/>
|
||||
<rect x="99" y="232" width="12" height="16" rx="4" fill="#e8b594"/>
|
||||
<circle cx="105" cy="218" r="22" fill="#f3c6a5"/>
|
||||
<path d="M83 216 q0 -30 31 -28 q19 1 21 22 q-13 -12 -30 -7 q-15 4 -22 13z" fill="#3a3a7d"/>
|
||||
</g>
|
||||
|
||||
<g>
|
||||
<path d="M478 332 h36 l-2 86 a6 6 0 0 1 -12 0 l-4 -52 -4 52 a6 6 0 0 1 -12 0 z" fill="#4f51a8"/>
|
||||
<ellipse cx="482" cy="420" rx="12" ry="6" fill="#34356f"/>
|
||||
<ellipse cx="510" cy="420" rx="12" ry="6" fill="#34356f"/>
|
||||
<path d="M512 258 q26 -16 30 -54" fill="none" stroke="#fff" stroke-width="15" stroke-linecap="round"/>
|
||||
<circle cx="543" cy="200" r="8" fill="#f3c6a5"/>
|
||||
<path d="M462 256 q26 -18 54 0 l6 80 h-66 z" fill="#fff" stroke="#dde3f7" stroke-width="2"/>
|
||||
<path d="M489 250 l-8 56 8 7 8 -7 -8 -56z" fill="#fde3df"/>
|
||||
<path d="M464 260 q-12 28 -6 54" fill="none" stroke="#fff" stroke-width="14" stroke-linecap="round"/>
|
||||
<circle cx="460" cy="316" r="7" fill="#f3c6a5"/>
|
||||
<rect x="483" y="232" width="12" height="16" rx="4" fill="#e8b594"/>
|
||||
<circle cx="489" cy="218" r="22" fill="#f3c6a5"/>
|
||||
<path d="M467 220 q-4 -32 28 -32 q24 0 22 30 q-2 14 -6 20 q4 -22 -8 -30 q4 12 -2 18 q-10 -20 -34 -6z" fill="#3a3a7d"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
{{ include('public/_hero_art.html.twig') }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -500,493 +395,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- ===================== Pre-Registration Modal ===================== -->
|
||||
<div id="regOverlay" style="display:none;position:fixed;inset:0;background:oklch(0.2 0.05 285 / 0.55);z-index:900;backdrop-filter:blur(4px);overflow-y:auto;padding:24px 16px" onclick="if(event.target===this)closeRegModal()">
|
||||
<div style="background:#fff;border-radius:20px;max-width:520px;margin:auto;padding:32px 28px;position:relative;box-shadow:0 24px 60px oklch(0.3 0.1 285 / 0.22)">
|
||||
<button onclick="closeRegModal()" aria-label="بستن" style="position:absolute;top:16px;left:20px;background:none;border:none;cursor:pointer;font-size:22px;color:var(--text-2);line-height:1">×</button>
|
||||
|
||||
<h2 style="margin:0 0 6px;font-size:20px;font-weight:800;color:var(--ink)">ثبت نام در کلینیک پرو</h2>
|
||||
<p style="margin:0 0 24px;font-size:13px;color:var(--text-2)">نوع حساب خود را انتخاب کنید</p>
|
||||
|
||||
<!-- Type Cards -->
|
||||
<div id="typeCards" style="display:flex;flex-direction:column;gap:10px;margin-bottom:22px">
|
||||
|
||||
<label class="reg-card" data-type="independent_doctor" style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid var(--border);border-radius:14px;cursor:pointer;transition:all .2s">
|
||||
<input type="radio" name="regType" value="independent_doctor" style="display:none">
|
||||
<span style="font-size:26px;flex-shrink:0">🩺</span>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px;color:var(--ink)">دکتر هستم</div>
|
||||
<div style="font-size:12px;color:var(--text-2);margin-top:2px">مطب شخصی دارم، به تنهایی کار میکنم</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="reg-card" data-type="doctor_with_clinic" style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid var(--border);border-radius:14px;cursor:pointer;transition:all .2s">
|
||||
<input type="radio" name="regType" value="doctor_with_clinic" style="display:none">
|
||||
<span style="font-size:26px;flex-shrink:0">🏥</span>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px;color:var(--ink)">دکتر هستم و کلینیک دارم</div>
|
||||
<div style="font-size:12px;color:var(--text-2);margin-top:2px">با چند دکتر در یک کلینیک همکاری میکنم</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="reg-card" data-type="clinic_manager" style="display:flex;align-items:center;gap:14px;padding:14px 16px;border:2px solid var(--border);border-radius:14px;cursor:pointer;transition:all .2s">
|
||||
<input type="radio" name="regType" value="clinic_manager" style="display:none">
|
||||
<span style="font-size:26px;flex-shrink:0">🏢</span>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px;color:var(--ink)">مدیر کلینیک هستم</div>
|
||||
<div style="font-size:12px;color:var(--text-2);margin-top:2px">مدیریت کلینیک را دارم، خودم دکتر نیستم</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- Form Fields -->
|
||||
<div id="regFields" style="display:flex;flex-direction:column;gap:14px">
|
||||
<div>
|
||||
<label style="display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink)">نام کامل
|
||||
<span style="color:var(--coral)">*</span>
|
||||
</label>
|
||||
<input id="regName" type="text" placeholder="مثال: دکتر علی احمدی" style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;color:var(--ink)"/>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink)">شماره موبایل
|
||||
<span style="color:var(--coral)">*</span>
|
||||
</label>
|
||||
<input id="regMobile" type="tel" placeholder="09xxxxxxxxx" dir="ltr" style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;color:var(--ink);text-align:right"/>
|
||||
</div>
|
||||
<div>
|
||||
<label style="display:block;font-size:13px;font-weight:600;margin-bottom:5px;color:var(--ink)">توضیحات
|
||||
<span style="font-weight:400;color:var(--text-2)">(اختیاری)</span>
|
||||
</label>
|
||||
<textarea id="regInfo" rows="3" placeholder="تخصص، آدرس، سابقه کاری، ..." style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 14px;font-size:14px;font-family:inherit;outline:none;box-sizing:border-box;resize:vertical;color:var(--ink)"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if altcha_enabled %}
|
||||
<!-- ALTCHA captcha — proof-of-work در پسزمینه (بدون تعامل کاربر) -->
|
||||
{# widget v3: attribute «challenge» (نه challengeurl قدیمی) #}
|
||||
<altcha-widget id="regAltcha" challenge="/api/v1/altcha/challenge" auto="onload" language="fa" style="display:block;margin-top:16px"></altcha-widget>
|
||||
{% endif %}
|
||||
|
||||
<!-- Error / Success -->
|
||||
<div id="regMsg" style="display:none;margin-top:14px;padding:12px 16px;border-radius:10px;font-size:13px"></div>
|
||||
|
||||
<button id="regSubmitBtn" disabled onclick="submitReg()" style="margin-top:20px;width:100%;background:var(--blue);color:#fff;border:none;border-radius:12px;padding:13px;font-size:15px;font-weight:700;cursor:pointer;font-family:inherit;opacity:.45;transition:opacity .2s">
|
||||
ارسال درخواست
|
||||
</button>
|
||||
<p style="text-align:center;font-size:12px;color:var(--text-2);margin:12px 0 0">پس از بررسی، اطلاعات ورود از طریق SMS ارسال میشود</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.reg-card:hover {
|
||||
border-color: var(--blue) !important;
|
||||
background: oklch(0.97 0.02 277);
|
||||
}
|
||||
.reg-card.selected {
|
||||
border-color: var(--blue) !important;
|
||||
background: oklch(0.96 0.03 277);
|
||||
}
|
||||
.reg-card.selected div > div:first-child {
|
||||
color: var(--blue);
|
||||
}
|
||||
#regName:focus,
|
||||
#regMobile:focus,
|
||||
#regInfo:focus {
|
||||
border-color: var(--blue);
|
||||
box-shadow: 0 0 0 3px oklch(0.58 0.185 277 / 0.12);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var overlay = document.getElementById('regOverlay');
|
||||
var submitBtn = document.getElementById('regSubmitBtn');
|
||||
var selectedType = null;
|
||||
|
||||
// payload حلشدهی ALTCHA (یکبارمصرف؛ در prod الزامی است)
|
||||
var regAltchaPayload = '';
|
||||
var regAltchaEl = document.getElementById('regAltcha');
|
||||
if (regAltchaEl)
|
||||
regAltchaEl.addEventListener('statechange', function (e) {
|
||||
if (e.detail && e.detail.state === 'verified')
|
||||
regAltchaPayload = e.detail.payload;
|
||||
});
|
||||
|
||||
function openRegModal() {
|
||||
overlay.style.display = 'block';
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
window.closeRegModal = function () {
|
||||
overlay.style.display = 'none';
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
|
||||
var btn1 = document.getElementById('openRegModal');
|
||||
var btn2 = document.getElementById('openRegModal2');
|
||||
var btn3 = document.getElementById('openRegModalNav');
|
||||
if (btn1)
|
||||
btn1.addEventListener('click', openRegModal);
|
||||
|
||||
|
||||
|
||||
if (btn2)
|
||||
btn2.addEventListener('click', openRegModal);
|
||||
|
||||
|
||||
|
||||
if (btn3)
|
||||
btn3.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
openRegModal();
|
||||
});
|
||||
|
||||
|
||||
|
||||
document.querySelectorAll('.reg-card').forEach(function (card) {
|
||||
card.addEventListener('click', function () {
|
||||
document.querySelectorAll('.reg-card').forEach(function (c) {
|
||||
c.classList.remove('selected');
|
||||
});
|
||||
card.classList.add('selected');
|
||||
var radio = card.querySelector('input[type=radio]');
|
||||
if (radio)
|
||||
radio.checked = true;
|
||||
|
||||
|
||||
|
||||
selectedType = card.dataset.type;
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.style.opacity = '1';
|
||||
});
|
||||
});
|
||||
|
||||
window.submitReg = function () {
|
||||
var name = document.getElementById('regName').value.trim();
|
||||
var mobile = document.getElementById('regMobile').value.trim();
|
||||
var info = document.getElementById('regInfo').value.trim();
|
||||
var msg = document.getElementById('regMsg');
|
||||
|
||||
if (! selectedType)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
if (! name) {
|
||||
showMsg('نام را وارد کنید', 'error');
|
||||
return;
|
||||
}
|
||||
if (! mobile || mobile.length < 10) {
|
||||
showMsg('شماره موبایل معتبر نیست', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.textContent = 'در حال ارسال...';
|
||||
|
||||
fetch('/api/v1/pre-registration', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(
|
||||
{
|
||||
type: selectedType,
|
||||
name: name,
|
||||
mobile: mobile,
|
||||
info: info || null,
|
||||
altcha: regAltchaPayload
|
||||
}
|
||||
)
|
||||
}).then(function (r) {
|
||||
return r.json();
|
||||
}).then(function (data) {
|
||||
if (data.success) {
|
||||
showMsg('درخواست شما ثبت شد. پس از بررسی، اطلاعات ورود از طریق SMS ارسال میشود.', 'success');
|
||||
submitBtn.textContent = 'ارسال شد ✓';
|
||||
setTimeout(function () {
|
||||
closeRegModal();
|
||||
}, 2200);
|
||||
} else {
|
||||
var errMsg = (data.errors && data.errors[0]) ? data.errors[0].message : 'خطایی رخ داد';
|
||||
showMsg(errMsg, 'error');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.style.opacity = '1';
|
||||
submitBtn.textContent = 'ارسال درخواست';
|
||||
resetRegAltcha();
|
||||
}
|
||||
}).catch(function () {
|
||||
showMsg('خطا در اتصال به سرور', 'error');
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.style.opacity = '1';
|
||||
submitBtn.textContent = 'ارسال درخواست';
|
||||
resetRegAltcha();
|
||||
});
|
||||
};
|
||||
|
||||
// challenge یکبارمصرف است؛ بعد از خطا یک challenge تازه بگیر.
|
||||
function resetRegAltcha() {
|
||||
regAltchaPayload = '';
|
||||
if (regAltchaEl && typeof regAltchaEl.reset === 'function')
|
||||
regAltchaEl.reset();
|
||||
}
|
||||
|
||||
function showMsg(text, type) {
|
||||
var msg = document.getElementById('regMsg');
|
||||
msg.textContent = text;
|
||||
msg.style.display = 'block';
|
||||
msg.style.background = type === 'success' ? '#dcfce7' : '#fef2f2';
|
||||
msg.style.color = type === 'success' ? '#16a34a' : '#ef4444';
|
||||
msg.style.border = type === 'success' ? '1px solid #bbf7d0' : '1px solid #fecaca';
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{{ include('public/_reg_modal.html.twig') }}
|
||||
|
||||
</main>
|
||||
|
||||
<!-- ===================== Footer ===================== -->
|
||||
<footer class="site-footer" id="contact">
|
||||
<div class="wrap">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-col footer-brand">
|
||||
<a class="brand" href="#hero">
|
||||
<b>کلینیک پرو</b>
|
||||
<span class="dot"></span>
|
||||
</a>
|
||||
<p>کلینیک پرو را ساختیم تا پزشکها بهجای درگیری با دفتر و کاغذ، حواسشان به کار اصلیشان باشد: بیمار.</p>
|
||||
<div class="foot-socials">
|
||||
<a href="#" aria-label="اینستاگرام">
|
||||
<svg viewbox="0 0 24 24" fill="none"><rect x="3" y="3" width="18" height="18" rx="5" stroke="currentColor" stroke-width="1.8"/><circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="1.8"/><circle cx="17.4" cy="6.6" r="1.2" fill="currentColor"/></svg>
|
||||
</a>
|
||||
<a href="#" aria-label="تلگرام">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M21 4 3 11l5 2 2 6 3-4 5 4 3-15Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
<a href="#" aria-label="واتساپ">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M4 20l1.4-4A8 8 0 1 1 9 18.6L4 20Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<!-- نماد اعتماد الکترونیکی — بعد از لود کامل صفحه تزریق میشود (footer JS) -->
|
||||
<div id="enamad-seal" style="margin-top:18px"></div>
|
||||
</div>
|
||||
{{ include('public/_footer.html.twig') }}
|
||||
|
||||
<div class="footer-col">
|
||||
<h4>دسترسی سریع</h4>
|
||||
<div class="foot-links">
|
||||
<a href="#features">امکانات</a>
|
||||
<a href="#why">چرا کلینیک پرو</a>
|
||||
<a href="#download" style="display:none">دانلود نرمافزار</a>
|
||||
<a href="#contact">تماس با ما</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-col">
|
||||
<h4>اطلاعات تماس</h4>
|
||||
<div class="foot-contact">
|
||||
<div class="fl">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M12 21s-7-5.2-7-11a7 7 0 0 1 14 0c0 5.8-7 11-7 11Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><circle cx="12" cy="10" r="2.6" stroke="currentColor" stroke-width="1.7"/></svg>
|
||||
<span>یاسوج، مهریان، خیابان شهید ستاره شیرازی، خیابان امامزاده احمد، پلاک ۸ شرکت توسعه فناوری اطلاعات حامی</span>
|
||||
</div>
|
||||
<div class="fl">
|
||||
<svg viewbox="0 0 24 24" fill="none"><path d="M4 6.5C4 5 5 4 6.5 4h2c.6 0 1.1.4 1.3 1l1 3c.2.6 0 1.2-.5 1.6L9 11c1 2 2.5 3.5 4.5 4.5l1.4-1.3c.4-.4 1-.6 1.6-.4l3 1c.6.2 1 .7 1 1.3v2c0 1.5-1 2.5-2.5 2.4C10.5 20 4 13.5 4 6.5Z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
<a href="tel:02191550875" style="font-variant-numeric:tabular-nums" dir="ltr">02191550875</a>
|
||||
|
||||
</div>
|
||||
<div class="fl">
|
||||
<svg viewbox="0 0 24 24" fill="none"><rect x="3" y="5" width="18" height="14" rx="2" stroke="currentColor" stroke-width="1.7"/><path d="m4 7 8 5 8-5" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/></svg>
|
||||
<a href="mailto:info@clinic-pro.ir" class="mono" dir="ltr">info@clinic-pro.ir</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-col" style="display:none">
|
||||
<h4>دانلود نرمافزار</h4>
|
||||
<div class="foot-badges">
|
||||
<a class="store-badge" href="#" style="background:oklch(1 0 0 / 0.08)">
|
||||
<svg viewbox="0 0 24 24" fill="currentColor"><path d="M16.4 12.6c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.9-3.5.9-.7 0-1.8-.8-3-.8-1.5 0-3 .9-3.7 2.3-1.6 2.8-.4 6.9 1.1 9.2.8 1.1 1.6 2.3 2.8 2.3 1.1 0 1.6-.7 2.9-.7 1.4 0 1.7.7 2.9.7 1.2 0 2-1.1 2.7-2.2.9-1.2 1.2-2.5 1.2-2.5s-2.3-.9-2.3-3.6ZM14.2 5.7c.6-.8 1-1.8.9-2.9-.9 0-2 .6-2.6 1.4-.6.7-1.1 1.7-.9 2.7 1 .1 2-.5 2.6-1.2Z"/></svg>
|
||||
<span class="sb-t">
|
||||
<small>دانلود برای</small>
|
||||
<b>مک · macOS</b>
|
||||
</span>
|
||||
</a>
|
||||
<a class="store-badge" href="#" style="background:oklch(1 0 0 / 0.08)">
|
||||
<svg viewbox="0 0 24 24" fill="currentColor"><path d="M3 5.5 10.5 4.4v7.1H3V5.5Zm0 13L10.5 19.6v-7H3v6Zm8.5 1.3L21 21V12.5h-9.5v7.3Zm0-15.6V11.5H21V3l-9.5 1.2Z"/></svg>
|
||||
<span class="sb-t">
|
||||
<small>دانلود برای</small>
|
||||
<b>ویندوز</b>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">© ۲۰۲۴ کلینیک پرو · ساختهشده برای پزشکان ایران</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
'use strict';
|
||||
var FA = [
|
||||
'۰',
|
||||
'۱',
|
||||
'۲',
|
||||
'۳',
|
||||
'۴',
|
||||
'۵',
|
||||
'۶',
|
||||
'۷',
|
||||
'۸',
|
||||
'۹'
|
||||
];
|
||||
function groupFa(n) {
|
||||
return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, '،').replace(/\d/g, function (d) {
|
||||
return FA[+ d];
|
||||
});
|
||||
}
|
||||
|
||||
var header = document.getElementById('header');
|
||||
function onScroll() {
|
||||
header.classList.toggle('scrolled', window.scrollY > 12);
|
||||
}
|
||||
window.addEventListener('scroll', onScroll, {passive: true});
|
||||
onScroll();
|
||||
|
||||
var navToggle = document.getElementById('navToggle');
|
||||
var navLinks = document.getElementById('navLinks');
|
||||
if (navToggle) {
|
||||
navToggle.addEventListener('click', function () {
|
||||
navLinks.classList.toggle('open');
|
||||
});
|
||||
navLinks.addEventListener('click', function (e) {
|
||||
if (e.target.tagName === 'A')
|
||||
navLinks.classList.remove('open');
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var sections = [
|
||||
'hero',
|
||||
'features',
|
||||
'why',
|
||||
'download',
|
||||
'contact'
|
||||
];
|
||||
var links = Array.prototype.slice.call(document.querySelectorAll('.nav-links a'));
|
||||
function syncActive() {
|
||||
var y = window.scrollY + 120,
|
||||
cur = 'hero';
|
||||
sections.forEach(function (id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el && el.offsetTop <= y)
|
||||
cur = id;
|
||||
|
||||
|
||||
|
||||
});
|
||||
links.forEach(function (a) {
|
||||
a.classList.toggle('active', a.getAttribute('href') === '#' + cur);
|
||||
});
|
||||
}
|
||||
window.addEventListener('scroll', syncActive, {passive: true});
|
||||
syncActive();
|
||||
|
||||
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
var reveals = Array.prototype.slice.call(document.querySelectorAll('.reveal'));
|
||||
function inView(el) {
|
||||
var r = el.getBoundingClientRect();
|
||||
return r.top<(window.innerHeight||document.documentElement.clientHeight)-30 && r.bottom> 0;
|
||||
}
|
||||
function reveal(el) {
|
||||
el.classList.add('in');
|
||||
}
|
||||
|
||||
if (reduce) {
|
||||
reveals.forEach(reveal);
|
||||
} else {
|
||||
reveals.forEach(function (el) {
|
||||
if (inView(el))
|
||||
reveal(el);
|
||||
|
||||
|
||||
|
||||
});
|
||||
if ('IntersectionObserver' in window) {
|
||||
var io = new IntersectionObserver(function (es) {
|
||||
es.forEach(function (e) {
|
||||
if (e.isIntersecting) {
|
||||
reveal(e.target);
|
||||
io.unobserve(e.target);
|
||||
}
|
||||
});
|
||||
}, {
|
||||
threshold: 0.12,
|
||||
rootMargin: '0px 0px -40px 0px'
|
||||
});
|
||||
reveals.forEach(function (el) {
|
||||
if (! el.classList.contains('in'))
|
||||
io.observe(el);
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
var ticking = false;
|
||||
function sweep() {
|
||||
if (ticking)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
ticking = true;
|
||||
requestAnimationFrame(function () {
|
||||
reveals.forEach(function (el) {
|
||||
if (inView(el))
|
||||
reveal(el);
|
||||
|
||||
|
||||
|
||||
});
|
||||
ticking = false;
|
||||
});
|
||||
}
|
||||
window.addEventListener('scroll', sweep, {passive: true});
|
||||
window.addEventListener('resize', sweep, {passive: true});
|
||||
setTimeout(function () {
|
||||
reveals.forEach(reveal);
|
||||
}, 2800);
|
||||
}
|
||||
|
||||
// نماد اعتماد الکترونیکی (Enamad) — فقط بعد از لود کامل صفحه تزریق میشود تا
|
||||
// درخواست تصویرِ دامنهی بیرونی با منابع خود سایت رقابت نکند و سرعت لود پایین نیاید.
|
||||
function mountEnamad() {
|
||||
var slot = document.getElementById('enamad-seal');
|
||||
if (! slot)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.setAttribute('referrerpolicy', 'origin');
|
||||
a.target = '_blank';
|
||||
a.href = 'https://trustseal.enamad.ir/?id=755841&Code=8sNSk0yrUE7EgbY9k5xkqTE0LaeXIaq4';
|
||||
var img = document.createElement('img');
|
||||
img.setAttribute('referrerpolicy', 'origin');
|
||||
img.src = 'https://trustseal.enamad.ir/logo.aspx?id=755841&Code=8sNSk0yrUE7EgbY9k5xkqTE0LaeXIaq4';
|
||||
img.alt = 'نماد اعتماد الکترونیکی';
|
||||
img.style.cursor = 'pointer';
|
||||
img.setAttribute('code', '8sNSk0yrUE7EgbY9k5xkqTE0LaeXIaq4');
|
||||
img.loading = 'lazy';
|
||||
a.appendChild(img);
|
||||
slot.appendChild(a);
|
||||
}
|
||||
if (document.readyState === 'complete') {
|
||||
mountEnamad();
|
||||
} else {
|
||||
window.addEventListener('load', mountEnamad);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{{ include('public/_page_scripts.html.twig') }}
|
||||
|
||||
{{ encore_entry_script_tags('home') }}
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
{# قالب مشترک صفحات فرود. تم دقیقاً همان صفحهٔ اصلی است — همان entry وبپک، همان هدر و
|
||||
فوتر و مودال. فقط متن و متادیتا از LandingPage میآید. #}
|
||||
{% set base = app.request.schemeAndHttpHost %}
|
||||
{% set url = base ~ '/' ~ page.slug %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>{{ page.metaTitle }}</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/logo.svg"/>
|
||||
<link rel="apple-touch-icon" href="/logo.svg"/>
|
||||
<meta name="description" content="{{ page.metaDescription }}"/>
|
||||
<meta name="keywords" content="{{ page.keywords }}"/>
|
||||
<link rel="canonical" href="{{ url }}"/>
|
||||
<meta name="robots" content="index, follow, max-image-preview:large"/>
|
||||
|
||||
<meta property="og:type" content="website"/>
|
||||
<meta property="og:site_name" content="کلینیک پرو"/>
|
||||
<meta property="og:title" content="{{ page.metaTitle }}"/>
|
||||
<meta property="og:description" content="{{ page.metaDescription }}"/>
|
||||
<meta property="og:url" content="{{ url }}"/>
|
||||
<meta property="og:image" content="{{ base }}/logo.svg"/>
|
||||
<meta property="og:locale" content="fa_IR"/>
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image"/>
|
||||
<meta name="twitter:title" content="{{ page.metaTitle }}"/>
|
||||
<meta name="twitter:description" content="{{ page.metaDescription }}"/>
|
||||
<meta name="twitter:image" content="{{ base }}/logo.svg"/>
|
||||
|
||||
{# JSON-LD با json_encode ساخته میشود نه رشتهٔ دستی: متن فارسی نقلقول و کاراکتر
|
||||
کنترلی دارد و JSONِ دستساز در Twig خیلی راحت نامعتبر میشود. #}
|
||||
<script type="application/ld+json">
|
||||
{{ {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
{
|
||||
'@type': 'SoftwareApplication',
|
||||
'@id': url ~ '#software',
|
||||
'name': page.h1,
|
||||
'applicationCategory': 'BusinessApplication',
|
||||
'operatingSystem': 'Web',
|
||||
'url': url,
|
||||
'description': page.metaDescription,
|
||||
'inLanguage': 'fa-IR',
|
||||
'offers': {
|
||||
'@type': 'Offer',
|
||||
'price': '0',
|
||||
'priceCurrency': 'IRR',
|
||||
'description': 'پلن رایگان برای شروع'
|
||||
},
|
||||
'publisher': { '@type': 'Organization', 'name': 'کلینیک پرو', 'url': base ~ '/' }
|
||||
},
|
||||
{
|
||||
'@type': 'BreadcrumbList',
|
||||
'@id': url ~ '#breadcrumb',
|
||||
'itemListElement': [
|
||||
{ '@type': 'ListItem', 'position': 1, 'name': 'کلینیک پرو', 'item': base ~ '/' },
|
||||
{ '@type': 'ListItem', 'position': 2, 'name': page.h1, 'item': url }
|
||||
]
|
||||
}
|
||||
]|merge(page.faq is not empty ? [{
|
||||
'@type': 'FAQPage',
|
||||
'@id': url ~ '#faq',
|
||||
'mainEntity': page.faq|map(item => {
|
||||
'@type': 'Question',
|
||||
'name': item.q,
|
||||
'acceptedAnswer': { '@type': 'Answer', 'text': item.a }
|
||||
})
|
||||
}] : [])
|
||||
}|json_encode(constant('JSON_UNESCAPED_UNICODE') b-or constant('JSON_UNESCAPED_SLASHES'))|raw }}
|
||||
</script>
|
||||
|
||||
{{ encore_entry_link_tags('home') }}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{{ include('public/_header.html.twig') }}
|
||||
|
||||
<main>
|
||||
<section class="hero" id="hero">
|
||||
<div class="wrap hero-grid">
|
||||
<div class="hero-copy">
|
||||
<h1 class="reveal">{{ page.h1 }}</h1>
|
||||
<p class="reveal d1">{{ page.lead }}</p>
|
||||
<div class="hero-actions reveal d2">
|
||||
{# همان idهایی که اسکریپت مودال به آنها bind میشود. #}
|
||||
<button class="btn btn-coral" id="openRegModal2">رایگان شروع کنید</button>
|
||||
<a href="#contact" class="btn btn-blue">درخواست دمو</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ include('public/_hero_art.html.twig') }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="fcols" id="features">
|
||||
<div class="wrap fcols-grid">
|
||||
{% for feature in page.features %}
|
||||
<div class="fcol reveal{% if loop.index0 % 3 == 1 %} d1{% elseif loop.index0 % 3 == 2 %} d2{% endif %}">
|
||||
<h3>{{ feature.title }}</h3>
|
||||
<p>{{ feature.body }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% if page.faq is not empty %}
|
||||
<section class="specs" id="faq">
|
||||
<div class="wrap">
|
||||
<h2 class="reveal">پرسشهای متداول</h2>
|
||||
<div class="fcols-grid">
|
||||
{% for item in page.faq %}
|
||||
<div class="fcol reveal">
|
||||
<h3>{{ item.q }}</h3>
|
||||
<p>{{ item.a }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if related is not empty %}
|
||||
<section class="band" id="related">
|
||||
<div class="wrap">
|
||||
<h2 class="reveal">راهکارهای دیگر کلینیک پرو</h2>
|
||||
<div class="fcols-grid">
|
||||
{% for item in related %}
|
||||
<div class="fcol reveal">
|
||||
<h3><a href="/{{ item.slug }}">{{ item.h1 }}</a></h3>
|
||||
<p>{{ item.metaDescription }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{{ include('public/_reg_modal.html.twig') }}
|
||||
</main>
|
||||
|
||||
{{ include('public/_footer.html.twig') }}
|
||||
{{ include('public/_page_scripts.html.twig') }}
|
||||
{{ encore_entry_script_tags('home') }}
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user