var/cache/dev/twig/b2/b235627aac0ae83b7fecef526a344b5f.php line 49

Open in your IDE?
  1. <?php
  2. use Twig\Environment;
  3. use Twig\Error\LoaderError;
  4. use Twig\Error\RuntimeError;
  5. use Twig\Extension\CoreExtension;
  6. use Twig\Extension\SandboxExtension;
  7. use Twig\Markup;
  8. use Twig\Sandbox\SecurityError;
  9. use Twig\Sandbox\SecurityNotAllowedTagError;
  10. use Twig\Sandbox\SecurityNotAllowedFilterError;
  11. use Twig\Sandbox\SecurityNotAllowedFunctionError;
  12. use Twig\Source;
  13. use Twig\Template;
  14. use Twig\TemplateWrapper;
  15. /* vitrine/en/homepage.html.twig */
  16. class __TwigTemplate_44de184e5eb1317f89ee043904cd3b74 extends Template
  17. {
  18. private Source $source;
  19. /**
  20. * @var array<string, Template>
  21. */
  22. private array $macros = [];
  23. public function __construct(Environment $env)
  24. {
  25. parent::__construct($env);
  26. $this->source = $this->getSourceContext();
  27. $this->blocks = [
  28. 'title' => [$this, 'block_title'],
  29. 'description' => [$this, 'block_description'],
  30. 'robots' => [$this, 'block_robots'],
  31. 'canonical' => [$this, 'block_canonical'],
  32. 'body' => [$this, 'block_body'],
  33. 'footerjs' => [$this, 'block_footerjs'],
  34. 'css' => [$this, 'block_css'],
  35. ];
  36. }
  37. protected function doGetParent(array $context): bool|string|Template|TemplateWrapper
  38. {
  39. // line 1
  40. return "vitrine/en/layout.html.twig";
  41. }
  42. protected function doDisplay(array $context, array $blocks = []): iterable
  43. {
  44. $macros = $this->macros;
  45. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  46. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "vitrine/en/homepage.html.twig"));
  47. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  48. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "template", "vitrine/en/homepage.html.twig"));
  49. $this->parent = $this->load("vitrine/en/layout.html.twig", 1);
  50. yield from $this->parent->unwrap()->yield($context, array_merge($this->blocks, $blocks));
  51. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  52. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  53. }
  54. // line 3
  55. /**
  56. * @return iterable<null|scalar|\Stringable>
  57. */
  58. public function block_title(array $context, array $blocks = []): iterable
  59. {
  60. $macros = $this->macros;
  61. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  62. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
  63. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  64. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "title"));
  65. yield "Cathedral Heritage Suite - 8-Guest Rental Strasbourg Center";
  66. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  67. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  68. yield from [];
  69. }
  70. // line 4
  71. /**
  72. * @return iterable<null|scalar|\Stringable>
  73. */
  74. public function block_description(array $context, array $blocks = []): iterable
  75. {
  76. $macros = $this->macros;
  77. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  78. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "description"));
  79. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  80. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "description"));
  81. yield "Rent our 83mΒ² suite in the heart of Strasbourg. 3 bedrooms, sleeps 8, 100m from Cathedral. Kitchen fully furnished, 2 bathrooms. Book your stay today!";
  82. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  83. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  84. yield from [];
  85. }
  86. // line 5
  87. /**
  88. * @return iterable<null|scalar|\Stringable>
  89. */
  90. public function block_robots(array $context, array $blocks = []): iterable
  91. {
  92. $macros = $this->macros;
  93. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  94. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "robots"));
  95. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  96. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "robots"));
  97. yield "index,follow";
  98. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  99. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  100. yield from [];
  101. }
  102. // line 7
  103. /**
  104. * @return iterable<null|scalar|\Stringable>
  105. */
  106. public function block_canonical(array $context, array $blocks = []): iterable
  107. {
  108. $macros = $this->macros;
  109. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  110. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "canonical"));
  111. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  112. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "canonical"));
  113. // line 8
  114. yield " <link rel=\"canonical\" href=\"https://cathedraleheritage.com\" />
  115. <link rel=\"alternate\" hreflang=\"fr\" href=\"https://cathedraleheritage.com/fr\" />
  116. <link rel=\"alternate\" hreflang=\"en\" href=\"https://cathedraleheritage.com\" />
  117. <link rel=\"alternate\" hreflang=\"x-default\" href=\"https://cathedraleheritage.com\" />
  118. ";
  119. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  120. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  121. yield from [];
  122. }
  123. // line 14
  124. /**
  125. * @return iterable<null|scalar|\Stringable>
  126. */
  127. public function block_body(array $context, array $blocks = []): iterable
  128. {
  129. $macros = $this->macros;
  130. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  131. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
  132. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  133. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "body"));
  134. // line 15
  135. yield "
  136. <section id=\"hero\" class=\"text-light no-top no-bottom relative overflow-hidden z-1000\">
  137. <div class=\"abs w-100 abs-centered z-2\">
  138. <div class=\"container\">
  139. <div class=\"spacer-double\"></div>
  140. <div class=\"row g-4 align-items-center justify-content-center\">
  141. <div class=\"col-md-8 text-center\">
  142. <h1 class=\"mb-2\" style=\"color:white;\">Welcome to Cathedral Heritage Suite</h1>
  143. <p class=\"lead mb-3\" style=\"color:white; font-size:22px;\">Beautifully appointed apartment accommodating up to 8 guests in Strasbourg's prestigious historical city center</p>
  144. <a class=\"btn-main btn-line bg-blur fx-slide\" href=\"#about\" style=\"color:white;\"><span>Find out more</span></a>
  145. </div>
  146. </div>
  147. </div>
  148. </div>
  149. <div class=\"vertical-center\">
  150. <div class=\"swiper\">
  151. <div class=\"swiper-wrapper\">
  152. <div class=\"swiper-slide\">
  153. <div class=\"swiper-inner\" data-bgimage=\"url(/images/salon2.jpeg)\">
  154. <div class=\"sw-overlay op-5\"></div>
  155. </div>
  156. </div>
  157. <div class=\"swiper-slide\">
  158. <div class=\"swiper-inner\" data-bgimage=\"url(/images/chambre2.jpeg)\">
  159. <div class=\"sw-overlay op-5\"></div>
  160. </div>
  161. </div>
  162. <div class=\"swiper-slide\">
  163. <div class=\"swiper-inner\" data-bgimage=\"url(/images/noel.jpeg)\">
  164. <div class=\"sw-overlay op-5\"></div>
  165. </div>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. <div class=\"abs w-100 bottom-0 z-2 pb-4 sm-hide\">
  171. <div class=\"container\">
  172. <div class=\"row\">
  173. <div class=\"col-lg-12\">
  174. <div class=\"d-flex justify-content-between\">
  175. <div><h6 style=\"color:white;\">Cathedral 100m away</h6></div>
  176. <div><h6 style=\"color:white;\">Museums 200m away</h6></div>
  177. <div><h6 style=\"color:white;\">Petite France 300m away</h6></div>
  178. </div>
  179. </div>
  180. </div>
  181. </div>
  182. </div>
  183. <div class=\"gradient-edge-bottom op-8\"></div>
  184. </section>
  185. <section id=\"about\">
  186. <div class=\"container\">
  187. <div class=\"row g-4 align-items-end justify-content-between\">
  188. <div class=\"col-lg-5\">
  189. <div class=\"subtitle\">About the apartment</div>
  190. <h2>Modern suite in the heart of Strasbourg's Grande Île</h2>
  191. </div>
  192. <div class=\"col-lg-4\">
  193. <p class=\"mb-4\" style=\"color:#212121;\">
  194. Spacious fully equipped appartement ideal for families and groups up to 8 people : 1 master bedroom with en-suite bathroom, one double bedroom, one bedroom with two double bunk beds (sleeps 4), maximum weight of 100kg for upper bunks.
  195. </p>
  196. <p class=\"mb-4\" style=\"color:#212121;\">
  197. Kitchen fully furnished and cozy living-dining room to share great moments together.
  198. </p>
  199. <p class=\"mb-4\" style=\"color:#212121;\">
  200. Amenities: hairdryer, dishwasher, washer-dryer, microwave, oven, ironing board with iron, Nespresso coffee machine, kettle, TV, Wi-Fi and USB outlets for charging your devices.
  201. </p>
  202. </div>
  203. </div>
  204. <div class=\"spacer-single\"></div>
  205. <div class=\"row g-4\">
  206. <div class=\"col-md-2\">
  207. <div class=\"relative\">
  208. <h5>Size</h5>
  209. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:6px;\">
  210. <img src=\"/images/home.png\" width=\"37\" class=\"me-3\" alt=\"\">
  211. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">83 mΒ²</div>
  212. </div>
  213. </div>
  214. </div>
  215. <div class=\"col-md-2\">
  216. <div class=\"relative\">
  217. <h5>Bedrooms</h5>
  218. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:4px;\">
  219. <img src=\"/images/bed.png\" width=\"37\" class=\"me-3\" alt=\"\">
  220. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">3</div>
  221. </div>
  222. </div>
  223. </div>
  224. <div class=\"col-md-2\">
  225. <div class=\"relative\">
  226. <h5>Living Room</h5>
  227. <div class=\"d-flex justify-content-start align-items-center\">
  228. <img src=\"/images/sofa.png\" width=\"50\" class=\"me-3\" alt=\"\">
  229. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">Included</div>
  230. </div>
  231. </div>
  232. </div>
  233. <div class=\"col-md-2\">
  234. <div class=\"relative\">
  235. <h5>Kitchen</h5>
  236. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:6px;\">
  237. <img src=\"/images/cooking.png\" width=\"37\" class=\"me-3\" alt=\"\">
  238. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">Included</div>
  239. </div>
  240. </div>
  241. </div>
  242. <div class=\"col-md-2\">
  243. <div class=\"relative\">
  244. <h5>Bathrooms</h5>
  245. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:4px;\">
  246. <img src=\"/images/bathroom.png\" width=\"40\" class=\"me-3\" alt=\"\">
  247. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">2</div>
  248. </div>
  249. </div>
  250. </div>
  251. <div class=\"col-md-2\">
  252. <div class=\"relative\">
  253. <h5>Guests</h5>
  254. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:5px;\">
  255. <img src=\"/images/user.png\" width=\"37\" class=\"me-3\" alt=\"\">
  256. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">8</div>
  257. </div>
  258. </div>
  259. </div>
  260. </div>
  261. </div>
  262. </section>
  263. <section id=\"rooms\" class=\"p-0 overflow-hidden\">
  264. <div class=\"container-fluid\">
  265. <div class=\"row\">
  266. <div class=\"col-lg-12\">
  267. <div class=\"owl-custom-nav menu-float\" data-target=\"#room-carousel\">
  268. <a class=\"btn-next\"></a>
  269. <a class=\"btn-prev\"></a>
  270. <div id=\"room-carousel\" class=\"owl-2-cols-center owl-carousel owl-theme\">
  271. <div class=\"item\">
  272. <div class=\"relative\">
  273. <div class=\"overflow-hidden text-light\">
  274. <div class=\"abs h-100 start-0 z-2 p-4\">
  275. <h3 style=\"color:white;\">Living Room</h3>
  276. </div>
  277. <img src=\"/images/salon2.jpeg\" class=\"w-100\" alt=\"Living Room\">
  278. </div>
  279. </div>
  280. </div>
  281. <div class=\"item\">
  282. <div class=\"relative\">
  283. <div class=\"overflow-hidden text-light\">
  284. <div class=\"abs h-100 start-1 z-2 p-4\">
  285. <h3 style=\"color:white;\">Bedroom 1</h3>
  286. </div>
  287. <img src=\"/images/chambre1.jpeg\" class=\"w-100\" alt=\"Bedroom 1\">
  288. </div>
  289. </div>
  290. </div>
  291. <div class=\"item\">
  292. <div class=\"relative\">
  293. <div class=\"overflow-hidden text-light\">
  294. <div class=\"abs h-100 start-2 z-2 p-4\">
  295. <h3 style=\"color:white;\">Bedroom 2</h3>
  296. </div>
  297. <img src=\"/images/chambre2.jpeg\" class=\"w-100\" alt=\"Bedroom 2\">
  298. </div>
  299. </div>
  300. </div>
  301. <div class=\"item\">
  302. <div class=\"relative\">
  303. <div class=\"overflow-hidden text-light\">
  304. <div class=\"abs h-100 start-3 z-2 p-4\">
  305. <h3 style=\"color:white;\">Bedroom 3</h3>
  306. </div>
  307. <img src=\"/images/chambre3.jpeg\" class=\"w-100\" alt=\"Bedroom 3\">
  308. </div>
  309. </div>
  310. </div>
  311. <div class=\"item\">
  312. <div class=\"relative\">
  313. <div class=\"overflow-hidden text-light\">
  314. <div class=\"abs h-100 start-4 z-2 p-4\">
  315. <h3 style=\"color:white;\">Kitchen</h3>
  316. </div>
  317. <img src=\"/images/cuisine.jpeg\" class=\"w-100\" alt=\"Kitchen\">
  318. </div>
  319. </div>
  320. </div>
  321. <div class=\"item\">
  322. <div class=\"relative\">
  323. <div class=\"overflow-hidden text-light\">
  324. <div class=\"abs h-100 start-5 z-2 p-4\">
  325. <h3 style=\"color:white;\">Bathroom</h3>
  326. </div>
  327. <img src=\"/images/salledebain.jpeg\" class=\"w-100\" alt=\"Bathroom 1\">
  328. </div>
  329. </div>
  330. </div>
  331. <div class=\"item\">
  332. <div class=\"relative\">
  333. <div class=\"overflow-hidden text-light\">
  334. <div class=\"abs h-100 start-6 z-2 p-4\">
  335. <h3 style=\"color:white;\">Bathroom 2</h3>
  336. </div>
  337. <img src=\"/images/salledebain2.jpeg\" class=\"w-100\" alt=\"Bathroom 2\">
  338. </div>
  339. </div>
  340. </div>
  341. </div>
  342. </div>
  343. </div>
  344. </div>
  345. </div>
  346. </section>
  347. <section id=\"services\" class=\"overlay-dark-1\">
  348. <div class=\"container\">
  349. <div class=\"row g-4 justify-content-between\">
  350. <div class=\"col-lg-5 relative z-3\">
  351. <div class=\"me-lg-3\">
  352. <div class=\"subtitle wow fadeInUp\" data-wow-delay=\".0s\">Your stay in Strasbourg</div>
  353. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">Rates and services</h2>
  354. <p style=\"color:#212121; font-size:18px;\">An exceptional suite in the heart of Strasbourg, with optionnal dedicated concierge service to assist you throughout your stay.</p>
  355. <p style=\"color:#212121; font-size:18px;\">Minimum booking of two nights.</p>
  356. <a href=\"#reservation\" class=\"btn-main\" style=\"color:white;\">Booking</a>
  357. </div>
  358. </div>
  359. <div class=\"col-lg-6\" style=\"color:black;\">
  360. <div class=\"spacer-single spacer-double\"></div>
  361. <div class=\"row\">
  362. <div class=\"col-md-6 wow fadeInUp\" data-wow-delay=\".2s\">
  363. ";
  364. // line 282
  365. yield "
  366. <ul class=\"ul-check fs-500\">
  367. <li>from €350 per night</li>
  368. <li>10% discount for bookings of 7 nights and up</li>
  369. </ul>
  370. </div>
  371. <div class=\"col-md-6 wow fadeInUp\" data-wow-delay=\".4s\">
  372. <h5 class=\"mb-3\">Optional services</h5>
  373. <ul class=\"ul-check fs-500\">
  374. <li>One parking space: €24/day or €150/week</li>
  375. <li>Extra cleaning during your stay : 60 euros</li>
  376. <li>Other Extras : Children's workshop, baby amenities, dog policy on request (other pets are unfortunately not allowed in the appartement), Decoration for special occasions, breakfast, Alsatian delicacies, etc</li>
  377. </ul>
  378. <div class=\"mt-4\">
  379. <p class=\"fs-500\">
  380. <strong>On site assistance</strong> <br />
  381. <small>Tuesday to Saturday β€’ 10am-6:45pm</small>
  382. </p>
  383. <p class=\"fs-500\">
  384. <strong>Private concierge subject to availability</strong><br>
  385. <small>Quotation on request</small>
  386. </p>
  387. </div>
  388. </div>
  389. </div>
  390. </div>
  391. </div>
  392. </div>
  393. </section>
  394. <section id=\"section-gallery\" class=\"relative\">
  395. <div class=\"container relative z-2\" id=\"photos\">
  396. <div class=\"row g-4 gx-5 justify-content-center\">
  397. <div class=\"col-lg-6 text-center\">
  398. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">Apartment Gallery</h2>
  399. <p class=\"wow fadeInUp\" data-wow-delay=\".3s\" style=\"color:#212121;\">Explore our curated images to discover the residence's various spaces β€” from the bedrooms and living area to the kitchen, bathroom, and outdoor surroundings.</p>
  400. </div>
  401. </div>
  402. <div class=\"row\">
  403. <div class=\"col-md-12 text-center\">
  404. <ul id=\"filters\" class=\"wow fadeInUp\" data-wow-delay=\"0s\">
  405. <li><a href=\"#\" data-filter=\"*\" class=\"selected\" style=\"color:#212121;\">Show All</a></li>
  406. <li><a href=\"#\" data-filter=\".chambre\" style=\"color:#212121;\">Bedrooms</a></li>
  407. <li><a href=\"#\" data-filter=\".salon\" style=\"color:#212121;\">Living Room</a></li>
  408. <li><a href=\"#\" data-filter=\".cuisine\" style=\"color:#212121;\">Kitchen</a></li>
  409. <li><a href=\"#\" data-filter=\".salledebain\" style=\"color:#212121;\">Bathroom</a></li>
  410. <li><a href=\"#\" data-filter=\".exterieur\" style=\"color:#212121;\">Outdoor surroundings</a></li>
  411. </ul>
  412. </div>
  413. </div>
  414. <div id=\"gallery\" class=\"row g-3 wow fadeInUp\" data-wow-delay=\".3s\">
  415. <div class=\"col-md-3 col-sm-6 col-12 item chambre\">
  416. <a href=\"images/chambre1.jpeg\" class=\"image-popup d-block hover\">
  417. <div class=\"relative overflow-hidden\">
  418. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  419. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  420. <img src=\"images/chambre1.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bedroom\">
  421. </div>
  422. </a>
  423. </div>
  424. <div class=\"col-md-3 col-sm-6 col-12 item chambre\">
  425. <a href=\"images/chambre2.jpeg\" class=\"image-popup d-block hover\">
  426. <div class=\"relative overflow-hidden\">
  427. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  428. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  429. <img src=\"images/chambre2.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bedroom 2\">
  430. </div>
  431. </a>
  432. </div>
  433. <div class=\"col-md-3 col-sm-6 col-12 item chambre\">
  434. <a href=\"images/chambre3.jpeg\" class=\"image-popup d-block hover\">
  435. <div class=\"relative overflow-hidden\">
  436. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  437. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  438. <img src=\"images/chambre3.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bedroom 3\">
  439. </div>
  440. </a>
  441. </div>
  442. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  443. <a href=\"images/salon.jpeg\" class=\"image-popup d-block hover\">
  444. <div class=\"relative overflow-hidden\">
  445. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  446. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  447. <img src=\"images/salon.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room\">
  448. </div>
  449. </a>
  450. </div>
  451. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  452. <a href=\"images/salon2.jpeg\" class=\"image-popup d-block hover\">
  453. <div class=\"relative overflow-hidden\">
  454. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  455. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  456. <img src=\"images/salon2.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 2\">
  457. </div>
  458. </a>
  459. </div>
  460. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  461. <a href=\"images/salon3.jpeg\" class=\"image-popup d-block hover\">
  462. <div class=\"relative overflow-hidden\">
  463. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  464. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  465. <img src=\"images/salon3.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 3\">
  466. </div>
  467. </a>
  468. </div>
  469. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  470. <a href=\"images/salon4.jpeg\" class=\"image-popup d-block hover\">
  471. <div class=\"relative overflow-hidden\">
  472. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  473. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  474. <img src=\"images/salon4.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 4\">
  475. </div>
  476. </a>
  477. </div>
  478. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  479. <a href=\"images/salon5.jpeg\" class=\"image-popup d-block hover\">
  480. <div class=\"relative overflow-hidden\">
  481. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  482. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  483. <img src=\"images/salon5.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 5\">
  484. </div>
  485. </a>
  486. </div>
  487. <div class=\"col-md-3 col-sm-6 col-12 item cuisine\">
  488. <a href=\"images/cuisine.jpeg\" class=\"image-popup d-block hover\">
  489. <div class=\"relative overflow-hidden\">
  490. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  491. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  492. <img src=\"images/cuisine.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Kitchen\">
  493. </div>
  494. </a>
  495. </div>
  496. <div class=\"col-md-3 col-sm-6 col-12 item salledebain\">
  497. <a href=\"images/salledebain.jpeg\" class=\"image-popup d-block hover\">
  498. <div class=\"relative overflow-hidden\">
  499. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  500. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  501. <img src=\"images/salledebain.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bathroom\">
  502. </div>
  503. </a>
  504. </div>
  505. <div class=\"col-md-3 col-sm-6 col-12 item salledebain\">
  506. <a href=\"images/salledebain2.jpeg\" class=\"image-popup d-block hover\">
  507. <div class=\"relative overflow-hidden\">
  508. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  509. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  510. <img src=\"images/salledebain2.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bathroom 2\">
  511. </div>
  512. </a>
  513. </div>
  514. <div class=\"col-md-3 col-sm-6 col-12 item exterieur\">
  515. <a href=\"images/exterieur.jpeg\" class=\"image-popup d-block hover\">
  516. <div class=\"relative overflow-hidden\">
  517. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  518. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  519. <img src=\"images/exterieur.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Exterior\">
  520. </div>
  521. </a>
  522. </div>
  523. </div>
  524. </div>
  525. </section>
  526. ";
  527. // line 453
  528. yield " ";
  529. // line 454
  530. yield " ";
  531. // line 455
  532. yield " <section id=\"reservation\" class=\"text-light\">
  533. <div class=\"container\">
  534. <div class=\"row g-4 justify-content-center\">
  535. <div class=\"col-lg-6 text-center\">
  536. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">Book your stay</h2>
  537. </div>
  538. </div>
  539. <div class=\"row g-4 justify-content-center\">
  540. <div class=\"col-lg-8\">
  541. <div class=\"booking-card\">
  542. ";
  543. // line 466
  544. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->renderBlock((isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 466, $this->source); })()), 'form_start');
  545. yield "
  546. ";
  547. // line 469
  548. yield " <div class=\"calendar-container\" style=\"height:300px;\">
  549. <input type=\"text\" id=\"date_range_picker\">
  550. </div>
  551. ";
  552. // line 474
  553. yield " <div class=\"row g-3 mt-2 dates-recap\">
  554. <div class=\"col-4 text-center\">
  555. <div class=\"recap-label\">Arrival</div>
  556. <div class=\"recap-value\" id=\"info-start\">-</div>
  557. </div>
  558. <div class=\"col-4 text-center\">
  559. <div class=\"recap-label\">Departure</div>
  560. <div class=\"recap-value\" id=\"info-end\">-</div>
  561. </div>
  562. <div class=\"col-4 text-center\">
  563. <div class=\"recap-label\">Nights</div>
  564. <div class=\"recap-value\" id=\"info-nights\">-</div>
  565. </div>
  566. </div>
  567. <hr class=\"booking-divider\">
  568. ";
  569. // line 492
  570. yield " <h4 class=\"booking-title\">Select rooms and guests</h4>
  571. <div class=\"counter-row\">
  572. <div class=\"counter-label\">
  573. <div class=\"counter-title\">Bedrooms</div>
  574. <div class=\"counter-sub\">Set by guest count</div>
  575. </div>
  576. <div class=\"counter-controls\">
  577. <button type=\"button\" class=\"counter-btn\" data-action=\"dec\" data-target=\"rooms\">βˆ’</button>
  578. <span class=\"counter-value\" id=\"cnt-rooms\">1</span>
  579. <button type=\"button\" class=\"counter-btn\" data-action=\"inc\" data-target=\"rooms\">+</button>
  580. </div>
  581. </div>
  582. <div class=\"counter-row\">
  583. <div class=\"counter-label\">
  584. <div class=\"counter-title\">Adults</div>
  585. </div>
  586. <div class=\"counter-controls\">
  587. <button type=\"button\" class=\"counter-btn\" data-action=\"dec\" data-target=\"adults\">βˆ’</button>
  588. <span class=\"counter-value\" id=\"cnt-adults\">2</span>
  589. <button type=\"button\" class=\"counter-btn\" data-action=\"inc\" data-target=\"adults\">+</button>
  590. </div>
  591. </div>
  592. <div class=\"counter-row\">
  593. <div class=\"counter-label\">
  594. <div class=\"counter-title\">Children</div>
  595. <div class=\"counter-sub\">1 - 17 years</div>
  596. </div>
  597. <div class=\"counter-controls\">
  598. <button type=\"button\" class=\"counter-btn\" data-action=\"dec\" data-target=\"children\">βˆ’</button>
  599. <span class=\"counter-value\" id=\"cnt-children\">0</span>
  600. <button type=\"button\" class=\"counter-btn\" data-action=\"inc\" data-target=\"children\">+</button>
  601. </div>
  602. </div>
  603. <div id=\"capacity-warning\" class=\"capacity-warning\" style=\"display:none;\"></div>
  604. ";
  605. // line 532
  606. yield " <div id=\"results\" class=\"mt-3\"></div>
  607. <hr class=\"booking-divider\">
  608. ";
  609. // line 537
  610. yield " <div class=\"row g-3\">
  611. <div class=\"col-md-6\">
  612. <label class=\"booking-label\">Last name</label>
  613. ";
  614. // line 540
  615. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 540, $this->source); })()), "lastname", [], "any", false, false, false, 540), 'widget');
  616. yield "
  617. </div>
  618. <div class=\"col-md-6\">
  619. <label class=\"booking-label\">First name</label>
  620. ";
  621. // line 544
  622. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 544, $this->source); })()), "name", [], "any", false, false, false, 544), 'widget');
  623. yield "
  624. </div>
  625. <div class=\"col-md-12\">
  626. <label class=\"booking-label\">Email address</label>
  627. ";
  628. // line 548
  629. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 548, $this->source); })()), "email", [], "any", false, false, false, 548), 'widget');
  630. yield "
  631. </div>
  632. <div class=\"col-md-12\">
  633. <label class=\"booking-label\">Message</label>
  634. ";
  635. // line 552
  636. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 552, $this->source); })()), "message", [], "any", false, false, false, 552), 'widget');
  637. yield "
  638. </div>
  639. </div>
  640. ";
  641. // line 557
  642. yield " <div class=\"text-center mt-4 cgv-block\">
  643. <input type=\"checkbox\" id=\"acceptCGV\" /> I accept the <a href=\"/terms\" target=\"_blank\" style=\"color:#212121; text-decoration:underline;\">terms and conditions of sale</a>
  644. </div>
  645. <div class=\"text-center mt-3\">
  646. <button type=\"submit\" name=\"submit\" value=\"1\" class=\"btn-main\" style=\"color:white;\">Send booking request</button>
  647. </div>
  648. ";
  649. // line 565
  650. yield " ";
  651. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 565, $this->source); })()), "start", [], "any", false, false, false, 565), 'widget');
  652. yield "
  653. ";
  654. // line 566
  655. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 566, $this->source); })()), "end", [], "any", false, false, false, 566), 'widget');
  656. yield "
  657. ";
  658. // line 567
  659. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 567, $this->source); })()), "rooms", [], "any", false, false, false, 567), 'widget');
  660. yield "
  661. ";
  662. // line 568
  663. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 568, $this->source); })()), "adults", [], "any", false, false, false, 568), 'widget');
  664. yield "
  665. ";
  666. // line 569
  667. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 569, $this->source); })()), "children", [], "any", false, false, false, 569), 'widget');
  668. yield "
  669. ";
  670. // line 570
  671. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(CoreExtension::getAttribute($this->env, $this->source, (isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 570, $this->source); })()), "persons", [], "any", false, false, false, 570), 'widget');
  672. yield "
  673. ";
  674. // line 572
  675. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock((isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 572, $this->source); })()), 'rest');
  676. yield "
  677. ";
  678. // line 573
  679. yield $this->env->getRuntime('Symfony\Component\Form\FormRenderer')->renderBlock((isset($context["form"]) || array_key_exists("form", $context) ? $context["form"] : (function () { throw new RuntimeError('Variable "form" does not exist.', 573, $this->source); })()), 'form_end');
  680. yield "
  681. </div>
  682. </div>
  683. </div>
  684. </div>
  685. </section>
  686. <section id=\"faq\" class=\"text-light\">
  687. <div class=\"container\">
  688. <div class=\"row g-4 justify-content-center\">
  689. <div class=\"col-lg-6 text-center\">
  690. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">FAQ</h2>
  691. </div>
  692. </div>
  693. <div class=\"row g-4 justify-content-center\">
  694. <div class=\"col-lg-6 text-left\" style=\"color:black !important;\">
  695. <h3 style=\"margin-top:7px;\">How can I book the accommodation?</h3>
  696. <div>You can book directly on our website and soon via partner platforms. Secure payment immediately confirms your reservation.</div>
  697. <h3 style=\"margin-top:7px;\">What are the check-in and check-out times?</h3>
  698. <div>
  699. <ul>
  700. <li>Check-in: from 3:00 PM</li>
  701. <li>Check-out: before 11:00 AM</li>
  702. </ul>
  703. </div>
  704. <h3 style=\"margin-top:7px;\">Is the accommodation fully equipped?</h3>
  705. <div> Yes, the apartment is fully furnished and equipped: kitchen, bedding, towels, appliances, Wi-Fi, and more.</div>
  706. <h3 style=\"margin-top:7px;\">Is parking available?</h3>
  707. <div>Yes, private parking is available as an option at €24 per 24 hours or €150 per week (7 nights).</div>
  708. <h3 style=\"margin-top:7px;\">Is the accommodation suitable for children?</h3>
  709. <div>Yes, we offer some baby amenities (baby cot, high chair, child-friendly tableware) upon request.</div>
  710. <h3 style=\"margin-top:7px;\"> Are pets allowed?</h3>
  711. <div> Please contact us before booking if you wish to bring a pet. Only dogs are accepted, and prior approval is required.</div>
  712. <h3 style=\"margin-top:7px;\">Can I cancel or modify my reservation?</h3>
  713. <div>Yes, our cancellation policy is provided at the time of booking:
  714. <ul>
  715. <li>85% refund if canceled more than 1 month before arrival</li>
  716. <li>50% refund if canceled between 1 month and 15 days before arrival</li>
  717. <li>No refund if canceled less than 15 days before arrival</li>
  718. </ul>
  719. </div>
  720. <h3 style=\"margin-top:7px;\">Is the accommodation accessible by public transport?</h3>
  721. <div>Yes, major transport options are nearby. The tram station \"Langstross, Grand'rue\" is less than 100 meters from the apartment, and Strasbourg train station is a 10-minute walk.</div>
  722. <h3 style=\"margin-top:7px;\">Are there shops or restaurants nearby?</h3>
  723. <div>Yes, you'll find supermarkets, cafΓ©s, restaurants, and tourist activities right at the foot of the building.</div>
  724. <h3 style=\"margin-top:7px;\"> What should I do if there's a problem during my stay?</h3>
  725. <div> We are available 24/7 by email for emergencies or questions about the apartment. You can also call us from 9:00 AM to 8:00 PM at +33 7 61 05 82 43, and we are available on-site on the ground floor of the building from Tuesday to Saturday, 10:00 AM to 6:45 PM.
  726. </div>
  727. </div>
  728. </div>
  729. </div>
  730. </section>
  731. ";
  732. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  733. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  734. yield from [];
  735. }
  736. // line 642
  737. /**
  738. * @return iterable<null|scalar|\Stringable>
  739. */
  740. public function block_footerjs(array $context, array $blocks = []): iterable
  741. {
  742. $macros = $this->macros;
  743. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  744. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "footerjs"));
  745. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  746. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "footerjs"));
  747. // line 643
  748. yield " <script src=\"https://cdn.jsdelivr.net/npm/flatpickr\"></script>
  749. ";
  750. // line 646
  751. yield " <script>
  752. window.PRICING_MATRIX = ";
  753. // line 647
  754. yield json_encode((isset($context["pricingMatrix"]) || array_key_exists("pricingMatrix", $context) ? $context["pricingMatrix"] : (function () { throw new RuntimeError('Variable "pricingMatrix" does not exist.', 647, $this->source); })()));
  755. yield ";
  756. window.SIMULATION_URL = \"";
  757. // line 648
  758. yield $this->extensions['Symfony\Bridge\Twig\Extension\RoutingExtension']->getPath("simulation_pricing");
  759. yield "\";
  760. console.log('πŸ“‹ Off-peak pricing matrix loaded:', window.PRICING_MATRIX);
  761. console.log('πŸ”— Simulation URL:', window.SIMULATION_URL);
  762. </script>
  763. <script>
  764. // ===========================================================
  765. // Bedrooms / adults / children logic
  766. //
  767. // Physical layout:
  768. // - Bedroom A: double bed β†’ 2 people
  769. // - Bedroom B: double bed β†’ 2 people
  770. // - Bedroom C: bunk beds β†’ 4 people (adults/children mix)
  771. //
  772. // The number of bedrooms is DETERMINED automatically (no choice):
  773. //
  774. // WITHOUT CHILDREN:
  775. // 1-2 ad β†’ 1 br
  776. // 3-4 ad β†’ 2 br
  777. // 5-8 ad β†’ 3 br
  778. //
  779. // WITH CHILDREN:
  780. // 1-2 ad β†’ 2 br (bedroom A + bunk room)
  781. // 3+ ad β†’ 3 br (A + B + bunk room)
  782. //
  783. // Constraints: adults + children ≀ 8, children ≀ 4, adults β‰₯ 1
  784. // ===========================================================
  785. function roomsForCombo(adults, children) {
  786. if (children > 0) {
  787. return adults <= 2 ? 2 : 3;
  788. }
  789. if (adults <= 2) return 1;
  790. if (adults <= 4) return 2;
  791. return 3;
  792. }
  793. function canAddAdult(state) {
  794. if (state.adults >= 8) return false;
  795. return (state.adults + 1 + state.children) <= 8;
  796. }
  797. function canAddChild(state) {
  798. if (state.children >= 4) return false;
  799. return (state.adults + state.children + 1) <= 8;
  800. }
  801. const state = { rooms: 1, adults: 2, children: 0 };
  802. function updateDisplay() {
  803. // Bedrooms count is recalculated automatically on each update
  804. state.rooms = roomsForCombo(state.adults, state.children);
  805. \$('#cnt-rooms').text(state.rooms);
  806. \$('#cnt-adults').text(state.adults);
  807. \$('#cnt-children').text(state.children);
  808. \$('#reservation_form_rooms').val(state.rooms);
  809. \$('#reservation_form_adults').val(state.adults);
  810. \$('#reservation_form_children').val(state.children);
  811. \$('#reservation_form_persons').val(state.adults + state.children);
  812. \$('.counter-btn').each(function() {
  813. const target = \$(this).data('target');
  814. const action = \$(this).data('action');
  815. let disabled = false;
  816. if (target === 'rooms') {
  817. // Bedrooms = always locked (set by adults/children)
  818. disabled = true;
  819. }
  820. if (target === 'adults') {
  821. if (action === 'dec' && state.adults <= 1) disabled = true;
  822. if (action === 'inc' && !canAddAdult(state)) disabled = true;
  823. }
  824. if (target === 'children') {
  825. if (action === 'dec' && state.children <= 0) disabled = true;
  826. if (action === 'inc' && !canAddChild(state)) disabled = true;
  827. }
  828. \$(this).prop('disabled', disabled).toggleClass('disabled', disabled);
  829. });
  830. \$('#capacity-warning').hide();
  831. }
  832. \$(document).on('click', '.counter-btn', function() {
  833. if (\$(this).prop('disabled')) return;
  834. const target = \$(this).data('target');
  835. const action = \$(this).data('action');
  836. // No action on \"rooms\" (always disabled)
  837. if (target === 'adults') {
  838. if (action === 'inc' && canAddAdult(state)) state.adults++;
  839. if (action === 'dec' && state.adults > 1) state.adults--;
  840. }
  841. if (target === 'children') {
  842. if (action === 'inc' && canAddChild(state)) state.children++;
  843. if (action === 'dec' && state.children > 0) state.children--;
  844. }
  845. updateDisplay();
  846. updateSimulation();
  847. });
  848. function updateSimulation() {
  849. const start = \$(\"#reservation_form_start\").val();
  850. const end = \$(\"#reservation_form_end\").val();
  851. const persons = state.adults + state.children;
  852. console.log('πŸ”„ updateSimulation', { start, end, rooms: state.rooms, adults: state.adults, children: state.children });
  853. if (!start || !end || persons < 1) {
  854. \$(\"#results\").html('');
  855. return;
  856. }
  857. \$(\"#results\").html('<div class=\"loading\" style=\"color:#212121;\">Calculating...</div>');
  858. \$.post(
  859. window.SIMULATION_URL,
  860. { start: start, end: end, rooms: state.rooms, adults: state.adults, children: state.children }
  861. )
  862. .done(function(data) {
  863. console.log('βœ… Simulation OK');
  864. \$(\"#results\").html(data);
  865. })
  866. .fail(function(xhr) {
  867. console.error('❌ Simulation KO', xhr.status, xhr.responseText);
  868. \$(\"#results\").html('<div class=\"error\" style=\"color:#a00;\">Error calculating price (' + xhr.status + ')</div>');
  869. });
  870. }
  871. \$(document).ready(function() {
  872. updateDisplay();
  873. \$('button[type=\"submit\"]').prop('disabled', true);
  874. \$('#acceptCGV').change(function() {
  875. \$('button[type=\"submit\"]').prop('disabled', !\$(this).is(':checked'));
  876. });
  877. });
  878. </script>
  879. <script>
  880. // ===========================================================
  881. // Flatpickr calendar
  882. // ===========================================================
  883. \$(document).ready(function() {
  884. let bookedRanges = [];
  885. \$.ajax({
  886. url: '";
  887. // line 802
  888. yield $this->env->getRuntime('Twig\Runtime\EscaperRuntime')->escape($this->extensions['App\Twig\CoreExtension']->getEnvironmentVariable("WEBHOOK_CALENDAR_AVAILABILITY"), "html", null, true);
  889. yield "',
  890. method: 'POST',
  891. contentType: 'application/json',
  892. data: ''
  893. })
  894. .done(function(data) {
  895. bookedRanges = data.bookings || [];
  896. initDatePicker();
  897. })
  898. .fail(function() { initDatePicker(); });
  899. function parseLocalDate(dateStr) {
  900. const [year, month, day] = dateStr.split('-').map(Number);
  901. return new Date(year, month - 1, day);
  902. }
  903. const isMobile = window.innerWidth <= 900;
  904. function initDatePicker() {
  905. flatpickr(\"#date_range_picker\", {
  906. inline: true,
  907. mode: \"range\",
  908. minDate: new Date(new Date().setDate(new Date().getDate() + 1)),
  909. dateFormat: \"Y-m-d\",
  910. showMonths: isMobile ? 1 : 2,
  911. disable: [
  912. function(date) {
  913. const checkDate = new Date(date);
  914. checkDate.setHours(0, 0, 0, 0);
  915. return bookedRanges.some(range => {
  916. const start = parseLocalDate(range.start_date);
  917. const end = parseLocalDate(range.end_date);
  918. return checkDate >= start && checkDate <= end;
  919. });
  920. }
  921. ],
  922. onChange: function(selectedDates, dateStr, instance) {
  923. if (selectedDates.length === 2) {
  924. const start = selectedDates[0];
  925. const end = selectedDates[1];
  926. if (isRangeAvailable(start, end)) {
  927. \$('#reservation_form_start').val(formatDate(start)).trigger('change');
  928. \$('#reservation_form_end').val(formatDate(end)).trigger('change');
  929. updateSelectedInfo(start, end);
  930. updateSimulation();
  931. } else {
  932. alert('⚠️ This period contains already booked dates.');
  933. instance.clear();
  934. clearSymfonyFields();
  935. hideSelectedInfo();
  936. \$(\"#results\").html('');
  937. }
  938. } else {
  939. clearSymfonyFields();
  940. hideSelectedInfo();
  941. \$(\"#results\").html('');
  942. }
  943. },
  944. onDayCreate: function(dObj, dStr, fp, dayElem) {
  945. const date = new Date(dayElem.dateObj);
  946. date.setHours(0, 0, 0, 0);
  947. const isBooked = bookedRanges.some(range => {
  948. const start = parseLocalDate(range.start_date);
  949. const end = parseLocalDate(range.end_date);
  950. return date >= start && date <= end;
  951. });
  952. if (isBooked) {
  953. dayElem.classList.add('booked');
  954. dayElem.title = 'Unavailable date (booked)';
  955. } else if (date >= new Date()) {
  956. dayElem.classList.add('available');
  957. }
  958. }
  959. });
  960. }
  961. function isRangeAvailable(startDate, endDate) {
  962. let currentDate = new Date(startDate);
  963. currentDate.setHours(0, 0, 0, 0);
  964. const endCheck = new Date(endDate);
  965. endCheck.setHours(0, 0, 0, 0);
  966. while (currentDate <= endCheck) {
  967. const isBooked = bookedRanges.some(range => {
  968. const start = parseLocalDate(range.start_date);
  969. const end = parseLocalDate(range.end_date);
  970. return currentDate >= start && currentDate <= end;
  971. });
  972. if (isBooked) return false;
  973. currentDate.setDate(currentDate.getDate() + 1);
  974. }
  975. return true;
  976. }
  977. function updateSelectedInfo(start, end) {
  978. const nights = Math.ceil((end - start) / (1000 * 60 * 60 * 24));
  979. \$('#info-start').text(start.toLocaleDateString('en-GB'));
  980. \$('#info-end').text(end.toLocaleDateString('en-GB'));
  981. \$('#info-nights').text(nights + ' night' + (nights > 1 ? 's' : ''));
  982. }
  983. function hideSelectedInfo() {
  984. \$('#info-start').text('-');
  985. \$('#info-end').text('-');
  986. \$('#info-nights').text('-');
  987. }
  988. function clearSymfonyFields() {
  989. \$('#reservation_form_start').val('');
  990. \$('#reservation_form_end').val('');
  991. }
  992. function formatDate(date) {
  993. return date.getFullYear() + '-' +
  994. String(date.getMonth() + 1).padStart(2, '0') + '-' +
  995. String(date.getDate()).padStart(2, '0');
  996. }
  997. });
  998. </script>
  999. ";
  1000. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  1001. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  1002. yield from [];
  1003. }
  1004. // line 926
  1005. /**
  1006. * @return iterable<null|scalar|\Stringable>
  1007. */
  1008. public function block_css(array $context, array $blocks = []): iterable
  1009. {
  1010. $macros = $this->macros;
  1011. $__internal_5a27a8ba21ca79b61932376b2fa922d2 = $this->extensions["Symfony\\Bundle\\WebProfilerBundle\\Twig\\WebProfilerExtension"];
  1012. $__internal_5a27a8ba21ca79b61932376b2fa922d2->enter($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "css"));
  1013. $__internal_6f47bbe9983af81f1e7450e9a3e3768f = $this->extensions["Symfony\\Bridge\\Twig\\Extension\\ProfilerExtension"];
  1014. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->enter($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof = new \Twig\Profiler\Profile($this->getTemplateName(), "block", "css"));
  1015. // line 927
  1016. yield " <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css\">
  1017. <style>
  1018. /* ===========================================================
  1019. Booking card (white border, transparent bg, black text)
  1020. =========================================================== */
  1021. .booking-card {
  1022. background: transparent;
  1023. border: 2px solid white;
  1024. border-radius: 12px;
  1025. padding: 32px;
  1026. color: #212121;
  1027. }
  1028. .booking-title {
  1029. color: #212121;
  1030. font-weight: 700;
  1031. margin-bottom: 24px;
  1032. }
  1033. .booking-divider {
  1034. border-top: 1px solid rgba(0,0,0,0.15);
  1035. margin: 28px 0;
  1036. }
  1037. .booking-label {
  1038. color: #212121;
  1039. font-weight: 500;
  1040. margin-bottom: 6px;
  1041. display: block;
  1042. }
  1043. .booking-card input.form-control,
  1044. .booking-card textarea.form-control {
  1045. background: rgba(255,255,255,0.85) !important;
  1046. border: 1px solid rgba(0,0,0,0.2) !important;
  1047. color: #212121 !important;
  1048. }
  1049. .booking-card input.form-control::placeholder,
  1050. .booking-card textarea.form-control::placeholder {
  1051. color: rgba(0,0,0,0.4) !important;
  1052. }
  1053. .booking-card input.form-control:focus,
  1054. .booking-card textarea.form-control:focus {
  1055. border-color: #212121 !important;
  1056. box-shadow: 0 0 0 0.2rem rgba(0,0,0,0.08) !important;
  1057. }
  1058. .cgv-block { color: #212121; }
  1059. .cgv-block a { color: #212121; text-decoration: underline; }
  1060. .dates-recap { color: #212121; }
  1061. .recap-label {
  1062. font-size: 13px;
  1063. text-transform: uppercase;
  1064. letter-spacing: 0.5px;
  1065. opacity: 0.7;
  1066. }
  1067. .recap-value {
  1068. font-size: 18px;
  1069. font-weight: 600;
  1070. margin-top: 4px;
  1071. }
  1072. .counter-row {
  1073. display: flex;
  1074. justify-content: space-between;
  1075. align-items: center;
  1076. padding: 14px 0;
  1077. border-bottom: 1px solid rgba(0,0,0,0.1);
  1078. }
  1079. .counter-row:last-of-type { border-bottom: none; }
  1080. .counter-title { font-size: 16px; font-weight: 500; color: #212121; }
  1081. .counter-sub { font-size: 12px; color: rgba(0,0,0,0.6); margin-top: 2px; }
  1082. .counter-controls { display: flex; align-items: center; gap: 12px; }
  1083. .counter-btn {
  1084. width: 40px;
  1085. height: 40px;
  1086. border-radius: 8px;
  1087. border: 1.5px solid #212121;
  1088. background: transparent;
  1089. color: #212121;
  1090. font-size: 20px;
  1091. font-weight: 600;
  1092. line-height: 1;
  1093. cursor: pointer;
  1094. transition: all 0.15s;
  1095. }
  1096. .counter-btn:hover:not(.disabled) { background: rgba(0,0,0,0.06); }
  1097. .counter-btn.disabled,
  1098. .counter-btn:disabled {
  1099. border-color: rgba(0,0,0,0.2);
  1100. color: rgba(0,0,0,0.25);
  1101. cursor: not-allowed;
  1102. background: transparent;
  1103. }
  1104. .counter-value {
  1105. min-width: 28px;
  1106. text-align: center;
  1107. font-size: 16px;
  1108. font-weight: 500;
  1109. color: #212121;
  1110. }
  1111. .capacity-warning {
  1112. margin-top: 12px;
  1113. padding: 10px 14px;
  1114. background: rgba(255,180,0,0.18);
  1115. border: 1px solid rgba(180,120,0,0.5);
  1116. border-radius: 6px;
  1117. color: #8a4500;
  1118. font-size: 14px;
  1119. }
  1120. .calendar-container {
  1121. margin: 0 0 8px 0;
  1122. width: 100%;
  1123. display: flex;
  1124. justify-content: center;
  1125. }
  1126. #date_range_picker { display: none; }
  1127. .flatpickr-calendar.inline {
  1128. box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  1129. border-radius: 8px;
  1130. }
  1131. .flatpickr-day.booked {
  1132. background-color: #ff4444 !important;
  1133. color: white !important;
  1134. cursor: not-allowed !important;
  1135. position: relative;
  1136. }
  1137. .flatpickr-day.booked::after {
  1138. content: \"βœ•\";
  1139. position: absolute;
  1140. top: 50%; left: 50%;
  1141. transform: translate(-50%, -50%);
  1142. font-size: 20px;
  1143. font-weight: bold;
  1144. }
  1145. .flatpickr-day.booked:hover { background-color: #ff0000 !important; }
  1146. .flatpickr-day.available:hover { background-color: #28a745; color: white; }
  1147. @media (max-width: 768px) {
  1148. .booking-card { padding: 20px; }
  1149. .calendar-container { margin: 0 0 8px 0; padding: 0; }
  1150. .flatpickr-calendar.inline { width: 100% !important; max-width: 100% !important; }
  1151. .flatpickr-months { padding: 8px 10px; }
  1152. .flatpickr-days { width: 100% !important; }
  1153. .dayContainer {
  1154. width: 100% !important;
  1155. min-width: 100% !important;
  1156. max-width: 100% !important;
  1157. }
  1158. .flatpickr-day {
  1159. height: 40px !important;
  1160. line-height: 40px !important;
  1161. flex-basis: 14.2857% !important;
  1162. max-width: 14.2857% !important;
  1163. }
  1164. }
  1165. </style>
  1166. ";
  1167. $__internal_6f47bbe9983af81f1e7450e9a3e3768f->leave($__internal_6f47bbe9983af81f1e7450e9a3e3768f_prof);
  1168. $__internal_5a27a8ba21ca79b61932376b2fa922d2->leave($__internal_5a27a8ba21ca79b61932376b2fa922d2_prof);
  1169. yield from [];
  1170. }
  1171. /**
  1172. * @codeCoverageIgnore
  1173. */
  1174. public function getTemplateName(): string
  1175. {
  1176. return "vitrine/en/homepage.html.twig";
  1177. }
  1178. /**
  1179. * @codeCoverageIgnore
  1180. */
  1181. public function isTraitable(): bool
  1182. {
  1183. return false;
  1184. }
  1185. /**
  1186. * @codeCoverageIgnore
  1187. */
  1188. public function getDebugInfo(): array
  1189. {
  1190. return array ( 1183 => 927, 1170 => 926, 1036 => 802, 879 => 648, 875 => 647, 872 => 646, 868 => 643, 855 => 642, 776 => 573, 772 => 572, 767 => 570, 763 => 569, 759 => 568, 755 => 567, 751 => 566, 746 => 565, 737 => 557, 730 => 552, 723 => 548, 716 => 544, 709 => 540, 704 => 537, 698 => 532, 657 => 492, 638 => 474, 632 => 469, 627 => 466, 614 => 455, 612 => 454, 610 => 453, 438 => 282, 179 => 15, 166 => 14, 151 => 8, 138 => 7, 115 => 5, 92 => 4, 69 => 3, 46 => 1,);
  1191. }
  1192. public function getSourceContext(): Source
  1193. {
  1194. return new Source("{% extends 'vitrine/en/layout.html.twig' %}
  1195. {% block title %}Cathedral Heritage Suite - 8-Guest Rental Strasbourg Center{% endblock title %}
  1196. {% block description %}Rent our 83mΒ² suite in the heart of Strasbourg. 3 bedrooms, sleeps 8, 100m from Cathedral. Kitchen fully furnished, 2 bathrooms. Book your stay today!{% endblock description %}
  1197. {% block robots %}index,follow{% endblock robots %}
  1198. {% block canonical %}
  1199. <link rel=\"canonical\" href=\"https://cathedraleheritage.com\" />
  1200. <link rel=\"alternate\" hreflang=\"fr\" href=\"https://cathedraleheritage.com/fr\" />
  1201. <link rel=\"alternate\" hreflang=\"en\" href=\"https://cathedraleheritage.com\" />
  1202. <link rel=\"alternate\" hreflang=\"x-default\" href=\"https://cathedraleheritage.com\" />
  1203. {% endblock canonical %}
  1204. {% block body %}
  1205. <section id=\"hero\" class=\"text-light no-top no-bottom relative overflow-hidden z-1000\">
  1206. <div class=\"abs w-100 abs-centered z-2\">
  1207. <div class=\"container\">
  1208. <div class=\"spacer-double\"></div>
  1209. <div class=\"row g-4 align-items-center justify-content-center\">
  1210. <div class=\"col-md-8 text-center\">
  1211. <h1 class=\"mb-2\" style=\"color:white;\">Welcome to Cathedral Heritage Suite</h1>
  1212. <p class=\"lead mb-3\" style=\"color:white; font-size:22px;\">Beautifully appointed apartment accommodating up to 8 guests in Strasbourg's prestigious historical city center</p>
  1213. <a class=\"btn-main btn-line bg-blur fx-slide\" href=\"#about\" style=\"color:white;\"><span>Find out more</span></a>
  1214. </div>
  1215. </div>
  1216. </div>
  1217. </div>
  1218. <div class=\"vertical-center\">
  1219. <div class=\"swiper\">
  1220. <div class=\"swiper-wrapper\">
  1221. <div class=\"swiper-slide\">
  1222. <div class=\"swiper-inner\" data-bgimage=\"url(/images/salon2.jpeg)\">
  1223. <div class=\"sw-overlay op-5\"></div>
  1224. </div>
  1225. </div>
  1226. <div class=\"swiper-slide\">
  1227. <div class=\"swiper-inner\" data-bgimage=\"url(/images/chambre2.jpeg)\">
  1228. <div class=\"sw-overlay op-5\"></div>
  1229. </div>
  1230. </div>
  1231. <div class=\"swiper-slide\">
  1232. <div class=\"swiper-inner\" data-bgimage=\"url(/images/noel.jpeg)\">
  1233. <div class=\"sw-overlay op-5\"></div>
  1234. </div>
  1235. </div>
  1236. </div>
  1237. </div>
  1238. </div>
  1239. <div class=\"abs w-100 bottom-0 z-2 pb-4 sm-hide\">
  1240. <div class=\"container\">
  1241. <div class=\"row\">
  1242. <div class=\"col-lg-12\">
  1243. <div class=\"d-flex justify-content-between\">
  1244. <div><h6 style=\"color:white;\">Cathedral 100m away</h6></div>
  1245. <div><h6 style=\"color:white;\">Museums 200m away</h6></div>
  1246. <div><h6 style=\"color:white;\">Petite France 300m away</h6></div>
  1247. </div>
  1248. </div>
  1249. </div>
  1250. </div>
  1251. </div>
  1252. <div class=\"gradient-edge-bottom op-8\"></div>
  1253. </section>
  1254. <section id=\"about\">
  1255. <div class=\"container\">
  1256. <div class=\"row g-4 align-items-end justify-content-between\">
  1257. <div class=\"col-lg-5\">
  1258. <div class=\"subtitle\">About the apartment</div>
  1259. <h2>Modern suite in the heart of Strasbourg's Grande Île</h2>
  1260. </div>
  1261. <div class=\"col-lg-4\">
  1262. <p class=\"mb-4\" style=\"color:#212121;\">
  1263. Spacious fully equipped appartement ideal for families and groups up to 8 people : 1 master bedroom with en-suite bathroom, one double bedroom, one bedroom with two double bunk beds (sleeps 4), maximum weight of 100kg for upper bunks.
  1264. </p>
  1265. <p class=\"mb-4\" style=\"color:#212121;\">
  1266. Kitchen fully furnished and cozy living-dining room to share great moments together.
  1267. </p>
  1268. <p class=\"mb-4\" style=\"color:#212121;\">
  1269. Amenities: hairdryer, dishwasher, washer-dryer, microwave, oven, ironing board with iron, Nespresso coffee machine, kettle, TV, Wi-Fi and USB outlets for charging your devices.
  1270. </p>
  1271. </div>
  1272. </div>
  1273. <div class=\"spacer-single\"></div>
  1274. <div class=\"row g-4\">
  1275. <div class=\"col-md-2\">
  1276. <div class=\"relative\">
  1277. <h5>Size</h5>
  1278. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:6px;\">
  1279. <img src=\"/images/home.png\" width=\"37\" class=\"me-3\" alt=\"\">
  1280. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">83 mΒ²</div>
  1281. </div>
  1282. </div>
  1283. </div>
  1284. <div class=\"col-md-2\">
  1285. <div class=\"relative\">
  1286. <h5>Bedrooms</h5>
  1287. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:4px;\">
  1288. <img src=\"/images/bed.png\" width=\"37\" class=\"me-3\" alt=\"\">
  1289. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">3</div>
  1290. </div>
  1291. </div>
  1292. </div>
  1293. <div class=\"col-md-2\">
  1294. <div class=\"relative\">
  1295. <h5>Living Room</h5>
  1296. <div class=\"d-flex justify-content-start align-items-center\">
  1297. <img src=\"/images/sofa.png\" width=\"50\" class=\"me-3\" alt=\"\">
  1298. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">Included</div>
  1299. </div>
  1300. </div>
  1301. </div>
  1302. <div class=\"col-md-2\">
  1303. <div class=\"relative\">
  1304. <h5>Kitchen</h5>
  1305. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:6px;\">
  1306. <img src=\"/images/cooking.png\" width=\"37\" class=\"me-3\" alt=\"\">
  1307. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">Included</div>
  1308. </div>
  1309. </div>
  1310. </div>
  1311. <div class=\"col-md-2\">
  1312. <div class=\"relative\">
  1313. <h5>Bathrooms</h5>
  1314. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:4px;\">
  1315. <img src=\"/images/bathroom.png\" width=\"40\" class=\"me-3\" alt=\"\">
  1316. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">2</div>
  1317. </div>
  1318. </div>
  1319. </div>
  1320. <div class=\"col-md-2\">
  1321. <div class=\"relative\">
  1322. <h5>Guests</h5>
  1323. <div class=\"d-flex justify-content-start align-items-center\" style=\"padding-top:5px;\">
  1324. <img src=\"/images/user.png\" width=\"37\" class=\"me-3\" alt=\"\">
  1325. <div class=\"fs-20 fw-600\" style=\"color:#212121;\">8</div>
  1326. </div>
  1327. </div>
  1328. </div>
  1329. </div>
  1330. </div>
  1331. </section>
  1332. <section id=\"rooms\" class=\"p-0 overflow-hidden\">
  1333. <div class=\"container-fluid\">
  1334. <div class=\"row\">
  1335. <div class=\"col-lg-12\">
  1336. <div class=\"owl-custom-nav menu-float\" data-target=\"#room-carousel\">
  1337. <a class=\"btn-next\"></a>
  1338. <a class=\"btn-prev\"></a>
  1339. <div id=\"room-carousel\" class=\"owl-2-cols-center owl-carousel owl-theme\">
  1340. <div class=\"item\">
  1341. <div class=\"relative\">
  1342. <div class=\"overflow-hidden text-light\">
  1343. <div class=\"abs h-100 start-0 z-2 p-4\">
  1344. <h3 style=\"color:white;\">Living Room</h3>
  1345. </div>
  1346. <img src=\"/images/salon2.jpeg\" class=\"w-100\" alt=\"Living Room\">
  1347. </div>
  1348. </div>
  1349. </div>
  1350. <div class=\"item\">
  1351. <div class=\"relative\">
  1352. <div class=\"overflow-hidden text-light\">
  1353. <div class=\"abs h-100 start-1 z-2 p-4\">
  1354. <h3 style=\"color:white;\">Bedroom 1</h3>
  1355. </div>
  1356. <img src=\"/images/chambre1.jpeg\" class=\"w-100\" alt=\"Bedroom 1\">
  1357. </div>
  1358. </div>
  1359. </div>
  1360. <div class=\"item\">
  1361. <div class=\"relative\">
  1362. <div class=\"overflow-hidden text-light\">
  1363. <div class=\"abs h-100 start-2 z-2 p-4\">
  1364. <h3 style=\"color:white;\">Bedroom 2</h3>
  1365. </div>
  1366. <img src=\"/images/chambre2.jpeg\" class=\"w-100\" alt=\"Bedroom 2\">
  1367. </div>
  1368. </div>
  1369. </div>
  1370. <div class=\"item\">
  1371. <div class=\"relative\">
  1372. <div class=\"overflow-hidden text-light\">
  1373. <div class=\"abs h-100 start-3 z-2 p-4\">
  1374. <h3 style=\"color:white;\">Bedroom 3</h3>
  1375. </div>
  1376. <img src=\"/images/chambre3.jpeg\" class=\"w-100\" alt=\"Bedroom 3\">
  1377. </div>
  1378. </div>
  1379. </div>
  1380. <div class=\"item\">
  1381. <div class=\"relative\">
  1382. <div class=\"overflow-hidden text-light\">
  1383. <div class=\"abs h-100 start-4 z-2 p-4\">
  1384. <h3 style=\"color:white;\">Kitchen</h3>
  1385. </div>
  1386. <img src=\"/images/cuisine.jpeg\" class=\"w-100\" alt=\"Kitchen\">
  1387. </div>
  1388. </div>
  1389. </div>
  1390. <div class=\"item\">
  1391. <div class=\"relative\">
  1392. <div class=\"overflow-hidden text-light\">
  1393. <div class=\"abs h-100 start-5 z-2 p-4\">
  1394. <h3 style=\"color:white;\">Bathroom</h3>
  1395. </div>
  1396. <img src=\"/images/salledebain.jpeg\" class=\"w-100\" alt=\"Bathroom 1\">
  1397. </div>
  1398. </div>
  1399. </div>
  1400. <div class=\"item\">
  1401. <div class=\"relative\">
  1402. <div class=\"overflow-hidden text-light\">
  1403. <div class=\"abs h-100 start-6 z-2 p-4\">
  1404. <h3 style=\"color:white;\">Bathroom 2</h3>
  1405. </div>
  1406. <img src=\"/images/salledebain2.jpeg\" class=\"w-100\" alt=\"Bathroom 2\">
  1407. </div>
  1408. </div>
  1409. </div>
  1410. </div>
  1411. </div>
  1412. </div>
  1413. </div>
  1414. </div>
  1415. </section>
  1416. <section id=\"services\" class=\"overlay-dark-1\">
  1417. <div class=\"container\">
  1418. <div class=\"row g-4 justify-content-between\">
  1419. <div class=\"col-lg-5 relative z-3\">
  1420. <div class=\"me-lg-3\">
  1421. <div class=\"subtitle wow fadeInUp\" data-wow-delay=\".0s\">Your stay in Strasbourg</div>
  1422. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">Rates and services</h2>
  1423. <p style=\"color:#212121; font-size:18px;\">An exceptional suite in the heart of Strasbourg, with optionnal dedicated concierge service to assist you throughout your stay.</p>
  1424. <p style=\"color:#212121; font-size:18px;\">Minimum booking of two nights.</p>
  1425. <a href=\"#reservation\" class=\"btn-main\" style=\"color:white;\">Booking</a>
  1426. </div>
  1427. </div>
  1428. <div class=\"col-lg-6\" style=\"color:black;\">
  1429. <div class=\"spacer-single spacer-double\"></div>
  1430. <div class=\"row\">
  1431. <div class=\"col-md-6 wow fadeInUp\" data-wow-delay=\".2s\">
  1432. {#
  1433. <h5 class=\" mb-3\">Peak Season</h5>
  1434. <p class=\"fs-500\"><small>June 1st to September 30th β€’ November 25th to January 5th</small></p>
  1435. <ul class=\"ul-check fs-500\">
  1436. <li>€960 per night</li>
  1437. <li>10% discount for bookings of 7 nights and up</li>
  1438. </ul>
  1439. <h5 class=\"mb-3 mt-4\">Off-peak Season</h5>
  1440. #}
  1441. <ul class=\"ul-check fs-500\">
  1442. <li>from €350 per night</li>
  1443. <li>10% discount for bookings of 7 nights and up</li>
  1444. </ul>
  1445. </div>
  1446. <div class=\"col-md-6 wow fadeInUp\" data-wow-delay=\".4s\">
  1447. <h5 class=\"mb-3\">Optional services</h5>
  1448. <ul class=\"ul-check fs-500\">
  1449. <li>One parking space: €24/day or €150/week</li>
  1450. <li>Extra cleaning during your stay : 60 euros</li>
  1451. <li>Other Extras : Children's workshop, baby amenities, dog policy on request (other pets are unfortunately not allowed in the appartement), Decoration for special occasions, breakfast, Alsatian delicacies, etc</li>
  1452. </ul>
  1453. <div class=\"mt-4\">
  1454. <p class=\"fs-500\">
  1455. <strong>On site assistance</strong> <br />
  1456. <small>Tuesday to Saturday β€’ 10am-6:45pm</small>
  1457. </p>
  1458. <p class=\"fs-500\">
  1459. <strong>Private concierge subject to availability</strong><br>
  1460. <small>Quotation on request</small>
  1461. </p>
  1462. </div>
  1463. </div>
  1464. </div>
  1465. </div>
  1466. </div>
  1467. </div>
  1468. </section>
  1469. <section id=\"section-gallery\" class=\"relative\">
  1470. <div class=\"container relative z-2\" id=\"photos\">
  1471. <div class=\"row g-4 gx-5 justify-content-center\">
  1472. <div class=\"col-lg-6 text-center\">
  1473. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">Apartment Gallery</h2>
  1474. <p class=\"wow fadeInUp\" data-wow-delay=\".3s\" style=\"color:#212121;\">Explore our curated images to discover the residence's various spaces β€” from the bedrooms and living area to the kitchen, bathroom, and outdoor surroundings.</p>
  1475. </div>
  1476. </div>
  1477. <div class=\"row\">
  1478. <div class=\"col-md-12 text-center\">
  1479. <ul id=\"filters\" class=\"wow fadeInUp\" data-wow-delay=\"0s\">
  1480. <li><a href=\"#\" data-filter=\"*\" class=\"selected\" style=\"color:#212121;\">Show All</a></li>
  1481. <li><a href=\"#\" data-filter=\".chambre\" style=\"color:#212121;\">Bedrooms</a></li>
  1482. <li><a href=\"#\" data-filter=\".salon\" style=\"color:#212121;\">Living Room</a></li>
  1483. <li><a href=\"#\" data-filter=\".cuisine\" style=\"color:#212121;\">Kitchen</a></li>
  1484. <li><a href=\"#\" data-filter=\".salledebain\" style=\"color:#212121;\">Bathroom</a></li>
  1485. <li><a href=\"#\" data-filter=\".exterieur\" style=\"color:#212121;\">Outdoor surroundings</a></li>
  1486. </ul>
  1487. </div>
  1488. </div>
  1489. <div id=\"gallery\" class=\"row g-3 wow fadeInUp\" data-wow-delay=\".3s\">
  1490. <div class=\"col-md-3 col-sm-6 col-12 item chambre\">
  1491. <a href=\"images/chambre1.jpeg\" class=\"image-popup d-block hover\">
  1492. <div class=\"relative overflow-hidden\">
  1493. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1494. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1495. <img src=\"images/chambre1.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bedroom\">
  1496. </div>
  1497. </a>
  1498. </div>
  1499. <div class=\"col-md-3 col-sm-6 col-12 item chambre\">
  1500. <a href=\"images/chambre2.jpeg\" class=\"image-popup d-block hover\">
  1501. <div class=\"relative overflow-hidden\">
  1502. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1503. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1504. <img src=\"images/chambre2.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bedroom 2\">
  1505. </div>
  1506. </a>
  1507. </div>
  1508. <div class=\"col-md-3 col-sm-6 col-12 item chambre\">
  1509. <a href=\"images/chambre3.jpeg\" class=\"image-popup d-block hover\">
  1510. <div class=\"relative overflow-hidden\">
  1511. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1512. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1513. <img src=\"images/chambre3.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bedroom 3\">
  1514. </div>
  1515. </a>
  1516. </div>
  1517. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  1518. <a href=\"images/salon.jpeg\" class=\"image-popup d-block hover\">
  1519. <div class=\"relative overflow-hidden\">
  1520. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1521. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1522. <img src=\"images/salon.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room\">
  1523. </div>
  1524. </a>
  1525. </div>
  1526. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  1527. <a href=\"images/salon2.jpeg\" class=\"image-popup d-block hover\">
  1528. <div class=\"relative overflow-hidden\">
  1529. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1530. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1531. <img src=\"images/salon2.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 2\">
  1532. </div>
  1533. </a>
  1534. </div>
  1535. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  1536. <a href=\"images/salon3.jpeg\" class=\"image-popup d-block hover\">
  1537. <div class=\"relative overflow-hidden\">
  1538. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1539. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1540. <img src=\"images/salon3.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 3\">
  1541. </div>
  1542. </a>
  1543. </div>
  1544. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  1545. <a href=\"images/salon4.jpeg\" class=\"image-popup d-block hover\">
  1546. <div class=\"relative overflow-hidden\">
  1547. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1548. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1549. <img src=\"images/salon4.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 4\">
  1550. </div>
  1551. </a>
  1552. </div>
  1553. <div class=\"col-md-3 col-sm-6 col-12 item salon\">
  1554. <a href=\"images/salon5.jpeg\" class=\"image-popup d-block hover\">
  1555. <div class=\"relative overflow-hidden\">
  1556. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1557. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1558. <img src=\"images/salon5.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Living Room 5\">
  1559. </div>
  1560. </a>
  1561. </div>
  1562. <div class=\"col-md-3 col-sm-6 col-12 item cuisine\">
  1563. <a href=\"images/cuisine.jpeg\" class=\"image-popup d-block hover\">
  1564. <div class=\"relative overflow-hidden\">
  1565. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1566. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1567. <img src=\"images/cuisine.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Kitchen\">
  1568. </div>
  1569. </a>
  1570. </div>
  1571. <div class=\"col-md-3 col-sm-6 col-12 item salledebain\">
  1572. <a href=\"images/salledebain.jpeg\" class=\"image-popup d-block hover\">
  1573. <div class=\"relative overflow-hidden\">
  1574. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1575. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1576. <img src=\"images/salledebain.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bathroom\">
  1577. </div>
  1578. </a>
  1579. </div>
  1580. <div class=\"col-md-3 col-sm-6 col-12 item salledebain\">
  1581. <a href=\"images/salledebain2.jpeg\" class=\"image-popup d-block hover\">
  1582. <div class=\"relative overflow-hidden\">
  1583. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1584. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1585. <img src=\"images/salledebain2.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Bathroom 2\">
  1586. </div>
  1587. </a>
  1588. </div>
  1589. <div class=\"col-md-3 col-sm-6 col-12 item exterieur\">
  1590. <a href=\"images/exterieur.jpeg\" class=\"image-popup d-block hover\">
  1591. <div class=\"relative overflow-hidden\">
  1592. <div class=\"absolute start-0 w-100 hover-op-1 p-5 abs-middle z-2 text-center text-white z-3\">View</div>
  1593. <div class=\"absolute start-0 w-100 h-100 overlay-dark-7 hover-op-1 z-2\"></div>
  1594. <img src=\"images/exterieur.jpeg\" class=\"w-100 hover-scale-1-2\" alt=\"Exterior\">
  1595. </div>
  1596. </a>
  1597. </div>
  1598. </div>
  1599. </div>
  1600. </section>
  1601. {# =================================================== #}
  1602. {# ============ BOOKING SECTION (refactored) ========= #}
  1603. {# =================================================== #}
  1604. <section id=\"reservation\" class=\"text-light\">
  1605. <div class=\"container\">
  1606. <div class=\"row g-4 justify-content-center\">
  1607. <div class=\"col-lg-6 text-center\">
  1608. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">Book your stay</h2>
  1609. </div>
  1610. </div>
  1611. <div class=\"row g-4 justify-content-center\">
  1612. <div class=\"col-lg-8\">
  1613. <div class=\"booking-card\">
  1614. {{ form_start(form) }}
  1615. {# ----- CALENDAR ----- #}
  1616. <div class=\"calendar-container\" style=\"height:300px;\">
  1617. <input type=\"text\" id=\"date_range_picker\">
  1618. </div>
  1619. {# ----- DATES RECAP (just below the calendar) ----- #}
  1620. <div class=\"row g-3 mt-2 dates-recap\">
  1621. <div class=\"col-4 text-center\">
  1622. <div class=\"recap-label\">Arrival</div>
  1623. <div class=\"recap-value\" id=\"info-start\">-</div>
  1624. </div>
  1625. <div class=\"col-4 text-center\">
  1626. <div class=\"recap-label\">Departure</div>
  1627. <div class=\"recap-value\" id=\"info-end\">-</div>
  1628. </div>
  1629. <div class=\"col-4 text-center\">
  1630. <div class=\"recap-label\">Nights</div>
  1631. <div class=\"recap-value\" id=\"info-nights\">-</div>
  1632. </div>
  1633. </div>
  1634. <hr class=\"booking-divider\">
  1635. {# ----- COUNTERS ----- #}
  1636. <h4 class=\"booking-title\">Select rooms and guests</h4>
  1637. <div class=\"counter-row\">
  1638. <div class=\"counter-label\">
  1639. <div class=\"counter-title\">Bedrooms</div>
  1640. <div class=\"counter-sub\">Set by guest count</div>
  1641. </div>
  1642. <div class=\"counter-controls\">
  1643. <button type=\"button\" class=\"counter-btn\" data-action=\"dec\" data-target=\"rooms\">βˆ’</button>
  1644. <span class=\"counter-value\" id=\"cnt-rooms\">1</span>
  1645. <button type=\"button\" class=\"counter-btn\" data-action=\"inc\" data-target=\"rooms\">+</button>
  1646. </div>
  1647. </div>
  1648. <div class=\"counter-row\">
  1649. <div class=\"counter-label\">
  1650. <div class=\"counter-title\">Adults</div>
  1651. </div>
  1652. <div class=\"counter-controls\">
  1653. <button type=\"button\" class=\"counter-btn\" data-action=\"dec\" data-target=\"adults\">βˆ’</button>
  1654. <span class=\"counter-value\" id=\"cnt-adults\">2</span>
  1655. <button type=\"button\" class=\"counter-btn\" data-action=\"inc\" data-target=\"adults\">+</button>
  1656. </div>
  1657. </div>
  1658. <div class=\"counter-row\">
  1659. <div class=\"counter-label\">
  1660. <div class=\"counter-title\">Children</div>
  1661. <div class=\"counter-sub\">1 - 17 years</div>
  1662. </div>
  1663. <div class=\"counter-controls\">
  1664. <button type=\"button\" class=\"counter-btn\" data-action=\"dec\" data-target=\"children\">βˆ’</button>
  1665. <span class=\"counter-value\" id=\"cnt-children\">0</span>
  1666. <button type=\"button\" class=\"counter-btn\" data-action=\"inc\" data-target=\"children\">+</button>
  1667. </div>
  1668. </div>
  1669. <div id=\"capacity-warning\" class=\"capacity-warning\" style=\"display:none;\"></div>
  1670. {# ----- PRICE RESULT ----- #}
  1671. <div id=\"results\" class=\"mt-3\"></div>
  1672. <hr class=\"booking-divider\">
  1673. {# ----- PERSONAL INFO ----- #}
  1674. <div class=\"row g-3\">
  1675. <div class=\"col-md-6\">
  1676. <label class=\"booking-label\">Last name</label>
  1677. {{ form_widget(form.lastname) }}
  1678. </div>
  1679. <div class=\"col-md-6\">
  1680. <label class=\"booking-label\">First name</label>
  1681. {{ form_widget(form.name) }}
  1682. </div>
  1683. <div class=\"col-md-12\">
  1684. <label class=\"booking-label\">Email address</label>
  1685. {{ form_widget(form.email) }}
  1686. </div>
  1687. <div class=\"col-md-12\">
  1688. <label class=\"booking-label\">Message</label>
  1689. {{ form_widget(form.message) }}
  1690. </div>
  1691. </div>
  1692. {# ----- T&C + SUBMIT ----- #}
  1693. <div class=\"text-center mt-4 cgv-block\">
  1694. <input type=\"checkbox\" id=\"acceptCGV\" /> I accept the <a href=\"/terms\" target=\"_blank\" style=\"color:#212121; text-decoration:underline;\">terms and conditions of sale</a>
  1695. </div>
  1696. <div class=\"text-center mt-3\">
  1697. <button type=\"submit\" name=\"submit\" value=\"1\" class=\"btn-main\" style=\"color:white;\">Send booking request</button>
  1698. </div>
  1699. {# Hidden fields #}
  1700. {{ form_widget(form.start) }}
  1701. {{ form_widget(form.end) }}
  1702. {{ form_widget(form.rooms) }}
  1703. {{ form_widget(form.adults) }}
  1704. {{ form_widget(form.children) }}
  1705. {{ form_widget(form.persons) }}
  1706. {{ form_rest(form) }}
  1707. {{ form_end(form) }}
  1708. </div>
  1709. </div>
  1710. </div>
  1711. </div>
  1712. </section>
  1713. <section id=\"faq\" class=\"text-light\">
  1714. <div class=\"container\">
  1715. <div class=\"row g-4 justify-content-center\">
  1716. <div class=\"col-lg-6 text-center\">
  1717. <h2 class=\"wow fadeInUp\" data-wow-delay=\".2s\">FAQ</h2>
  1718. </div>
  1719. </div>
  1720. <div class=\"row g-4 justify-content-center\">
  1721. <div class=\"col-lg-6 text-left\" style=\"color:black !important;\">
  1722. <h3 style=\"margin-top:7px;\">How can I book the accommodation?</h3>
  1723. <div>You can book directly on our website and soon via partner platforms. Secure payment immediately confirms your reservation.</div>
  1724. <h3 style=\"margin-top:7px;\">What are the check-in and check-out times?</h3>
  1725. <div>
  1726. <ul>
  1727. <li>Check-in: from 3:00 PM</li>
  1728. <li>Check-out: before 11:00 AM</li>
  1729. </ul>
  1730. </div>
  1731. <h3 style=\"margin-top:7px;\">Is the accommodation fully equipped?</h3>
  1732. <div> Yes, the apartment is fully furnished and equipped: kitchen, bedding, towels, appliances, Wi-Fi, and more.</div>
  1733. <h3 style=\"margin-top:7px;\">Is parking available?</h3>
  1734. <div>Yes, private parking is available as an option at €24 per 24 hours or €150 per week (7 nights).</div>
  1735. <h3 style=\"margin-top:7px;\">Is the accommodation suitable for children?</h3>
  1736. <div>Yes, we offer some baby amenities (baby cot, high chair, child-friendly tableware) upon request.</div>
  1737. <h3 style=\"margin-top:7px;\"> Are pets allowed?</h3>
  1738. <div> Please contact us before booking if you wish to bring a pet. Only dogs are accepted, and prior approval is required.</div>
  1739. <h3 style=\"margin-top:7px;\">Can I cancel or modify my reservation?</h3>
  1740. <div>Yes, our cancellation policy is provided at the time of booking:
  1741. <ul>
  1742. <li>85% refund if canceled more than 1 month before arrival</li>
  1743. <li>50% refund if canceled between 1 month and 15 days before arrival</li>
  1744. <li>No refund if canceled less than 15 days before arrival</li>
  1745. </ul>
  1746. </div>
  1747. <h3 style=\"margin-top:7px;\">Is the accommodation accessible by public transport?</h3>
  1748. <div>Yes, major transport options are nearby. The tram station \"Langstross, Grand'rue\" is less than 100 meters from the apartment, and Strasbourg train station is a 10-minute walk.</div>
  1749. <h3 style=\"margin-top:7px;\">Are there shops or restaurants nearby?</h3>
  1750. <div>Yes, you'll find supermarkets, cafΓ©s, restaurants, and tourist activities right at the foot of the building.</div>
  1751. <h3 style=\"margin-top:7px;\"> What should I do if there's a problem during my stay?</h3>
  1752. <div> We are available 24/7 by email for emergencies or questions about the apartment. You can also call us from 9:00 AM to 8:00 PM at +33 7 61 05 82 43, and we are available on-site on the ground floor of the building from Tuesday to Saturday, 10:00 AM to 6:45 PM.
  1753. </div>
  1754. </div>
  1755. </div>
  1756. </div>
  1757. </section>
  1758. {% endblock body %}
  1759. {% block footerjs %}
  1760. <script src=\"https://cdn.jsdelivr.net/npm/flatpickr\"></script>
  1761. {# Pricing matrix + simulation URL exposed to JS #}
  1762. <script>
  1763. window.PRICING_MATRIX = {{ pricingMatrix|json_encode|raw }};
  1764. window.SIMULATION_URL = \"{{ path('simulation_pricing') }}\";
  1765. console.log('πŸ“‹ Off-peak pricing matrix loaded:', window.PRICING_MATRIX);
  1766. console.log('πŸ”— Simulation URL:', window.SIMULATION_URL);
  1767. </script>
  1768. <script>
  1769. // ===========================================================
  1770. // Bedrooms / adults / children logic
  1771. //
  1772. // Physical layout:
  1773. // - Bedroom A: double bed β†’ 2 people
  1774. // - Bedroom B: double bed β†’ 2 people
  1775. // - Bedroom C: bunk beds β†’ 4 people (adults/children mix)
  1776. //
  1777. // The number of bedrooms is DETERMINED automatically (no choice):
  1778. //
  1779. // WITHOUT CHILDREN:
  1780. // 1-2 ad β†’ 1 br
  1781. // 3-4 ad β†’ 2 br
  1782. // 5-8 ad β†’ 3 br
  1783. //
  1784. // WITH CHILDREN:
  1785. // 1-2 ad β†’ 2 br (bedroom A + bunk room)
  1786. // 3+ ad β†’ 3 br (A + B + bunk room)
  1787. //
  1788. // Constraints: adults + children ≀ 8, children ≀ 4, adults β‰₯ 1
  1789. // ===========================================================
  1790. function roomsForCombo(adults, children) {
  1791. if (children > 0) {
  1792. return adults <= 2 ? 2 : 3;
  1793. }
  1794. if (adults <= 2) return 1;
  1795. if (adults <= 4) return 2;
  1796. return 3;
  1797. }
  1798. function canAddAdult(state) {
  1799. if (state.adults >= 8) return false;
  1800. return (state.adults + 1 + state.children) <= 8;
  1801. }
  1802. function canAddChild(state) {
  1803. if (state.children >= 4) return false;
  1804. return (state.adults + state.children + 1) <= 8;
  1805. }
  1806. const state = { rooms: 1, adults: 2, children: 0 };
  1807. function updateDisplay() {
  1808. // Bedrooms count is recalculated automatically on each update
  1809. state.rooms = roomsForCombo(state.adults, state.children);
  1810. \$('#cnt-rooms').text(state.rooms);
  1811. \$('#cnt-adults').text(state.adults);
  1812. \$('#cnt-children').text(state.children);
  1813. \$('#reservation_form_rooms').val(state.rooms);
  1814. \$('#reservation_form_adults').val(state.adults);
  1815. \$('#reservation_form_children').val(state.children);
  1816. \$('#reservation_form_persons').val(state.adults + state.children);
  1817. \$('.counter-btn').each(function() {
  1818. const target = \$(this).data('target');
  1819. const action = \$(this).data('action');
  1820. let disabled = false;
  1821. if (target === 'rooms') {
  1822. // Bedrooms = always locked (set by adults/children)
  1823. disabled = true;
  1824. }
  1825. if (target === 'adults') {
  1826. if (action === 'dec' && state.adults <= 1) disabled = true;
  1827. if (action === 'inc' && !canAddAdult(state)) disabled = true;
  1828. }
  1829. if (target === 'children') {
  1830. if (action === 'dec' && state.children <= 0) disabled = true;
  1831. if (action === 'inc' && !canAddChild(state)) disabled = true;
  1832. }
  1833. \$(this).prop('disabled', disabled).toggleClass('disabled', disabled);
  1834. });
  1835. \$('#capacity-warning').hide();
  1836. }
  1837. \$(document).on('click', '.counter-btn', function() {
  1838. if (\$(this).prop('disabled')) return;
  1839. const target = \$(this).data('target');
  1840. const action = \$(this).data('action');
  1841. // No action on \"rooms\" (always disabled)
  1842. if (target === 'adults') {
  1843. if (action === 'inc' && canAddAdult(state)) state.adults++;
  1844. if (action === 'dec' && state.adults > 1) state.adults--;
  1845. }
  1846. if (target === 'children') {
  1847. if (action === 'inc' && canAddChild(state)) state.children++;
  1848. if (action === 'dec' && state.children > 0) state.children--;
  1849. }
  1850. updateDisplay();
  1851. updateSimulation();
  1852. });
  1853. function updateSimulation() {
  1854. const start = \$(\"#reservation_form_start\").val();
  1855. const end = \$(\"#reservation_form_end\").val();
  1856. const persons = state.adults + state.children;
  1857. console.log('πŸ”„ updateSimulation', { start, end, rooms: state.rooms, adults: state.adults, children: state.children });
  1858. if (!start || !end || persons < 1) {
  1859. \$(\"#results\").html('');
  1860. return;
  1861. }
  1862. \$(\"#results\").html('<div class=\"loading\" style=\"color:#212121;\">Calculating...</div>');
  1863. \$.post(
  1864. window.SIMULATION_URL,
  1865. { start: start, end: end, rooms: state.rooms, adults: state.adults, children: state.children }
  1866. )
  1867. .done(function(data) {
  1868. console.log('βœ… Simulation OK');
  1869. \$(\"#results\").html(data);
  1870. })
  1871. .fail(function(xhr) {
  1872. console.error('❌ Simulation KO', xhr.status, xhr.responseText);
  1873. \$(\"#results\").html('<div class=\"error\" style=\"color:#a00;\">Error calculating price (' + xhr.status + ')</div>');
  1874. });
  1875. }
  1876. \$(document).ready(function() {
  1877. updateDisplay();
  1878. \$('button[type=\"submit\"]').prop('disabled', true);
  1879. \$('#acceptCGV').change(function() {
  1880. \$('button[type=\"submit\"]').prop('disabled', !\$(this).is(':checked'));
  1881. });
  1882. });
  1883. </script>
  1884. <script>
  1885. // ===========================================================
  1886. // Flatpickr calendar
  1887. // ===========================================================
  1888. \$(document).ready(function() {
  1889. let bookedRanges = [];
  1890. \$.ajax({
  1891. url: '{{ env('WEBHOOK_CALENDAR_AVAILABILITY') }}',
  1892. method: 'POST',
  1893. contentType: 'application/json',
  1894. data: ''
  1895. })
  1896. .done(function(data) {
  1897. bookedRanges = data.bookings || [];
  1898. initDatePicker();
  1899. })
  1900. .fail(function() { initDatePicker(); });
  1901. function parseLocalDate(dateStr) {
  1902. const [year, month, day] = dateStr.split('-').map(Number);
  1903. return new Date(year, month - 1, day);
  1904. }
  1905. const isMobile = window.innerWidth <= 900;
  1906. function initDatePicker() {
  1907. flatpickr(\"#date_range_picker\", {
  1908. inline: true,
  1909. mode: \"range\",
  1910. minDate: new Date(new Date().setDate(new Date().getDate() + 1)),
  1911. dateFormat: \"Y-m-d\",
  1912. showMonths: isMobile ? 1 : 2,
  1913. disable: [
  1914. function(date) {
  1915. const checkDate = new Date(date);
  1916. checkDate.setHours(0, 0, 0, 0);
  1917. return bookedRanges.some(range => {
  1918. const start = parseLocalDate(range.start_date);
  1919. const end = parseLocalDate(range.end_date);
  1920. return checkDate >= start && checkDate <= end;
  1921. });
  1922. }
  1923. ],
  1924. onChange: function(selectedDates, dateStr, instance) {
  1925. if (selectedDates.length === 2) {
  1926. const start = selectedDates[0];
  1927. const end = selectedDates[1];
  1928. if (isRangeAvailable(start, end)) {
  1929. \$('#reservation_form_start').val(formatDate(start)).trigger('change');
  1930. \$('#reservation_form_end').val(formatDate(end)).trigger('change');
  1931. updateSelectedInfo(start, end);
  1932. updateSimulation();
  1933. } else {
  1934. alert('⚠️ This period contains already booked dates.');
  1935. instance.clear();
  1936. clearSymfonyFields();
  1937. hideSelectedInfo();
  1938. \$(\"#results\").html('');
  1939. }
  1940. } else {
  1941. clearSymfonyFields();
  1942. hideSelectedInfo();
  1943. \$(\"#results\").html('');
  1944. }
  1945. },
  1946. onDayCreate: function(dObj, dStr, fp, dayElem) {
  1947. const date = new Date(dayElem.dateObj);
  1948. date.setHours(0, 0, 0, 0);
  1949. const isBooked = bookedRanges.some(range => {
  1950. const start = parseLocalDate(range.start_date);
  1951. const end = parseLocalDate(range.end_date);
  1952. return date >= start && date <= end;
  1953. });
  1954. if (isBooked) {
  1955. dayElem.classList.add('booked');
  1956. dayElem.title = 'Unavailable date (booked)';
  1957. } else if (date >= new Date()) {
  1958. dayElem.classList.add('available');
  1959. }
  1960. }
  1961. });
  1962. }
  1963. function isRangeAvailable(startDate, endDate) {
  1964. let currentDate = new Date(startDate);
  1965. currentDate.setHours(0, 0, 0, 0);
  1966. const endCheck = new Date(endDate);
  1967. endCheck.setHours(0, 0, 0, 0);
  1968. while (currentDate <= endCheck) {
  1969. const isBooked = bookedRanges.some(range => {
  1970. const start = parseLocalDate(range.start_date);
  1971. const end = parseLocalDate(range.end_date);
  1972. return currentDate >= start && currentDate <= end;
  1973. });
  1974. if (isBooked) return false;
  1975. currentDate.setDate(currentDate.getDate() + 1);
  1976. }
  1977. return true;
  1978. }
  1979. function updateSelectedInfo(start, end) {
  1980. const nights = Math.ceil((end - start) / (1000 * 60 * 60 * 24));
  1981. \$('#info-start').text(start.toLocaleDateString('en-GB'));
  1982. \$('#info-end').text(end.toLocaleDateString('en-GB'));
  1983. \$('#info-nights').text(nights + ' night' + (nights > 1 ? 's' : ''));
  1984. }
  1985. function hideSelectedInfo() {
  1986. \$('#info-start').text('-');
  1987. \$('#info-end').text('-');
  1988. \$('#info-nights').text('-');
  1989. }
  1990. function clearSymfonyFields() {
  1991. \$('#reservation_form_start').val('');
  1992. \$('#reservation_form_end').val('');
  1993. }
  1994. function formatDate(date) {
  1995. return date.getFullYear() + '-' +
  1996. String(date.getMonth() + 1).padStart(2, '0') + '-' +
  1997. String(date.getDate()).padStart(2, '0');
  1998. }
  1999. });
  2000. </script>
  2001. {% endblock footerjs %}
  2002. {% block css %}
  2003. <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css\">
  2004. <style>
  2005. /* ===========================================================
  2006. Booking card (white border, transparent bg, black text)
  2007. =========================================================== */
  2008. .booking-card {
  2009. background: transparent;
  2010. border: 2px solid white;
  2011. border-radius: 12px;
  2012. padding: 32px;
  2013. color: #212121;
  2014. }
  2015. .booking-title {
  2016. color: #212121;
  2017. font-weight: 700;
  2018. margin-bottom: 24px;
  2019. }
  2020. .booking-divider {
  2021. border-top: 1px solid rgba(0,0,0,0.15);
  2022. margin: 28px 0;
  2023. }
  2024. .booking-label {
  2025. color: #212121;
  2026. font-weight: 500;
  2027. margin-bottom: 6px;
  2028. display: block;
  2029. }
  2030. .booking-card input.form-control,
  2031. .booking-card textarea.form-control {
  2032. background: rgba(255,255,255,0.85) !important;
  2033. border: 1px solid rgba(0,0,0,0.2) !important;
  2034. color: #212121 !important;
  2035. }
  2036. .booking-card input.form-control::placeholder,
  2037. .booking-card textarea.form-control::placeholder {
  2038. color: rgba(0,0,0,0.4) !important;
  2039. }
  2040. .booking-card input.form-control:focus,
  2041. .booking-card textarea.form-control:focus {
  2042. border-color: #212121 !important;
  2043. box-shadow: 0 0 0 0.2rem rgba(0,0,0,0.08) !important;
  2044. }
  2045. .cgv-block { color: #212121; }
  2046. .cgv-block a { color: #212121; text-decoration: underline; }
  2047. .dates-recap { color: #212121; }
  2048. .recap-label {
  2049. font-size: 13px;
  2050. text-transform: uppercase;
  2051. letter-spacing: 0.5px;
  2052. opacity: 0.7;
  2053. }
  2054. .recap-value {
  2055. font-size: 18px;
  2056. font-weight: 600;
  2057. margin-top: 4px;
  2058. }
  2059. .counter-row {
  2060. display: flex;
  2061. justify-content: space-between;
  2062. align-items: center;
  2063. padding: 14px 0;
  2064. border-bottom: 1px solid rgba(0,0,0,0.1);
  2065. }
  2066. .counter-row:last-of-type { border-bottom: none; }
  2067. .counter-title { font-size: 16px; font-weight: 500; color: #212121; }
  2068. .counter-sub { font-size: 12px; color: rgba(0,0,0,0.6); margin-top: 2px; }
  2069. .counter-controls { display: flex; align-items: center; gap: 12px; }
  2070. .counter-btn {
  2071. width: 40px;
  2072. height: 40px;
  2073. border-radius: 8px;
  2074. border: 1.5px solid #212121;
  2075. background: transparent;
  2076. color: #212121;
  2077. font-size: 20px;
  2078. font-weight: 600;
  2079. line-height: 1;
  2080. cursor: pointer;
  2081. transition: all 0.15s;
  2082. }
  2083. .counter-btn:hover:not(.disabled) { background: rgba(0,0,0,0.06); }
  2084. .counter-btn.disabled,
  2085. .counter-btn:disabled {
  2086. border-color: rgba(0,0,0,0.2);
  2087. color: rgba(0,0,0,0.25);
  2088. cursor: not-allowed;
  2089. background: transparent;
  2090. }
  2091. .counter-value {
  2092. min-width: 28px;
  2093. text-align: center;
  2094. font-size: 16px;
  2095. font-weight: 500;
  2096. color: #212121;
  2097. }
  2098. .capacity-warning {
  2099. margin-top: 12px;
  2100. padding: 10px 14px;
  2101. background: rgba(255,180,0,0.18);
  2102. border: 1px solid rgba(180,120,0,0.5);
  2103. border-radius: 6px;
  2104. color: #8a4500;
  2105. font-size: 14px;
  2106. }
  2107. .calendar-container {
  2108. margin: 0 0 8px 0;
  2109. width: 100%;
  2110. display: flex;
  2111. justify-content: center;
  2112. }
  2113. #date_range_picker { display: none; }
  2114. .flatpickr-calendar.inline {
  2115. box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  2116. border-radius: 8px;
  2117. }
  2118. .flatpickr-day.booked {
  2119. background-color: #ff4444 !important;
  2120. color: white !important;
  2121. cursor: not-allowed !important;
  2122. position: relative;
  2123. }
  2124. .flatpickr-day.booked::after {
  2125. content: \"βœ•\";
  2126. position: absolute;
  2127. top: 50%; left: 50%;
  2128. transform: translate(-50%, -50%);
  2129. font-size: 20px;
  2130. font-weight: bold;
  2131. }
  2132. .flatpickr-day.booked:hover { background-color: #ff0000 !important; }
  2133. .flatpickr-day.available:hover { background-color: #28a745; color: white; }
  2134. @media (max-width: 768px) {
  2135. .booking-card { padding: 20px; }
  2136. .calendar-container { margin: 0 0 8px 0; padding: 0; }
  2137. .flatpickr-calendar.inline { width: 100% !important; max-width: 100% !important; }
  2138. .flatpickr-months { padding: 8px 10px; }
  2139. .flatpickr-days { width: 100% !important; }
  2140. .dayContainer {
  2141. width: 100% !important;
  2142. min-width: 100% !important;
  2143. max-width: 100% !important;
  2144. }
  2145. .flatpickr-day {
  2146. height: 40px !important;
  2147. line-height: 40px !important;
  2148. flex-basis: 14.2857% !important;
  2149. max-width: 14.2857% !important;
  2150. }
  2151. }
  2152. </style>
  2153. {% endblock css %}
  2154. ", "vitrine/en/homepage.html.twig", "/var/www/vhosts/mirtillostudio.com/ch.mirtillostudio.com/templates/vitrine/en/homepage.html.twig");
  2155. }
  2156. }