templates/school/index.html.twig line 1

Open in your IDE?
  1. {% extends 'layout/frontEndLayout.html.twig' %}
  2. {% block name %}
  3. Welcome to LiveEdu
  4. {% endblock %}
  5. {% block stylesheets %}
  6. {{ parent() }}
  7. <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700;900&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
  8. <style>
  9. :root {
  10. --gold: #C9A84C;
  11. --gold-light: #E8D5A3;
  12. --navy: #0A1628;
  13. --navy-mid: #112244;
  14. --white: #FAFAF8;
  15. --cream: #F5F0E8;
  16. --text-muted: #8A8A8A;
  17. --accent: #2C6BAD;
  18. }
  19. * { margin: 0; padding: 0; box-sizing: border-box; }
  20. body {
  21. font-family: 'DM Sans', sans-serif;
  22. background: var(--white);
  23. color: var(--navy);
  24. }
  25. /* ─── HERO SLIDER ─────────────────────────────────────── */
  26. .hero-slider {
  27. position: relative;
  28. height: 100vh;
  29. min-height: 600px;
  30. overflow: hidden;
  31. }
  32. .carousel-item-custom {
  33. position: absolute;
  34. inset: 0;
  35. opacity: 0;
  36. transition: opacity 1s ease;
  37. background-size: cover;
  38. background-position: center;
  39. }
  40. .carousel-item-custom.active { opacity: 1; }
  41. .hero-overlay {
  42. position: absolute;
  43. inset: 0;
  44. background: linear-gradient(
  45. 135deg,
  46. rgba(10,22,40,0.85) 0%,
  47. rgba(17,34,68,0.60) 60%,
  48. rgba(201,168,76,0.15) 100%
  49. );
  50. }
  51. .hero-content {
  52. position: absolute;
  53. inset: 0;
  54. display: flex;
  55. flex-direction: column;
  56. justify-content: center;
  57. padding: 0 8vw;
  58. max-width: 900px;
  59. }
  60. .hero-label {
  61. font-family: 'DM Sans', sans-serif;
  62. font-size: 0.75rem;
  63. font-weight: 600;
  64. letter-spacing: 0.35em;
  65. text-transform: uppercase;
  66. color: var(--gold);
  67. margin-bottom: 1.5rem;
  68. opacity: 0;
  69. transform: translateY(20px);
  70. animation: fadeUp 0.8s ease 0.3s forwards;
  71. }
  72. .hero-title {
  73. font-family: 'Playfair Display', serif;
  74. font-size: clamp(2.5rem, 6vw, 5rem);
  75. font-weight: 900;
  76. line-height: 1.1;
  77. color: var(--white);
  78. margin-bottom: 1.5rem;
  79. opacity: 0;
  80. transform: translateY(30px);
  81. animation: fadeUp 0.9s ease 0.5s forwards;
  82. }
  83. .hero-title em {
  84. font-style: italic;
  85. color: var(--gold);
  86. }
  87. .hero-sub {
  88. font-size: 1.1rem;
  89. font-weight: 300;
  90. color: rgba(255,255,255,0.75);
  91. max-width: 480px;
  92. line-height: 1.7;
  93. opacity: 0;
  94. transform: translateY(20px);
  95. animation: fadeUp 0.9s ease 0.7s forwards;
  96. }
  97. .hero-cta {
  98. margin-top: 2.5rem;
  99. display: flex;
  100. gap: 1rem;
  101. opacity: 0;
  102. animation: fadeUp 0.9s ease 0.9s forwards;
  103. }
  104. .btn-gold {
  105. padding: 0.85rem 2rem;
  106. background: var(--gold);
  107. color: var(--navy);
  108. font-weight: 600;
  109. font-size: 0.9rem;
  110. letter-spacing: 0.05em;
  111. border: none;
  112. cursor: pointer;
  113. text-decoration: none;
  114. transition: all 0.3s ease;
  115. }
  116. .btn-gold:hover { background: var(--gold-light); transform: translateY(-2px); }
  117. .btn-outline-white {
  118. padding: 0.85rem 2rem;
  119. background: transparent;
  120. color: var(--white);
  121. font-weight: 500;
  122. font-size: 0.9rem;
  123. letter-spacing: 0.05em;
  124. border: 1px solid rgba(255,255,255,0.4);
  125. cursor: pointer;
  126. text-decoration: none;
  127. transition: all 0.3s ease;
  128. }
  129. .btn-outline-white:hover { border-color: var(--gold); color: var(--gold); }
  130. /* Slider decorative bar */
  131. .hero-bar {
  132. position: absolute;
  133. right: 0;
  134. top: 0;
  135. bottom: 0;
  136. width: 6px;
  137. background: var(--gold);
  138. }
  139. /* Slide counter */
  140. .slide-counter {
  141. position: absolute;
  142. bottom: 2.5rem;
  143. right: 3rem;
  144. color: rgba(255,255,255,0.5);
  145. font-size: 0.8rem;
  146. letter-spacing: 0.2em;
  147. font-weight: 500;
  148. }
  149. .slide-counter span { color: var(--gold); font-size: 1.1rem; }
  150. /* Carousel indicators */
  151. .hero-indicators {
  152. position: absolute;
  153. bottom: 2.5rem;
  154. left: 8vw;
  155. display: flex;
  156. gap: 0.6rem;
  157. list-style: none;
  158. }
  159. .hero-indicators li {
  160. width: 28px;
  161. height: 2px;
  162. background: rgba(255,255,255,0.3);
  163. cursor: pointer;
  164. transition: all 0.3s;
  165. }
  166. .hero-indicators li.active {
  167. width: 52px;
  168. background: var(--gold);
  169. }
  170. /* Carousel controls */
  171. .hero-prev, .hero-next {
  172. position: absolute;
  173. top: 50%;
  174. transform: translateY(-50%);
  175. width: 52px;
  176. height: 52px;
  177. border: 1px solid rgba(255,255,255,0.25);
  178. background: rgba(10,22,40,0.4);
  179. backdrop-filter: blur(8px);
  180. color: white;
  181. display: flex;
  182. align-items: center;
  183. justify-content: center;
  184. font-size: 1.1rem;
  185. cursor: pointer;
  186. transition: all 0.3s;
  187. text-decoration: none;
  188. z-index: 10;
  189. }
  190. .hero-prev { left: 2rem; }
  191. .hero-next { right: 2rem; }
  192. .hero-prev:hover, .hero-next:hover {
  193. background: var(--gold);
  194. border-color: var(--gold);
  195. color: var(--navy);
  196. }
  197. @keyframes fadeUp {
  198. to { opacity: 1; transform: translateY(0); }
  199. }
  200. /* ─── STATS BAR ──────────────────────────────────────── */
  201. .stats-bar {
  202. background: var(--navy);
  203. padding: 0;
  204. display: grid;
  205. grid-template-columns: repeat(4, 1fr);
  206. }
  207. .stat-item {
  208. padding: 2rem 1.5rem;
  209. text-align: center;
  210. border-right: 1px solid rgba(255,255,255,0.06);
  211. transition: background 0.3s;
  212. }
  213. .stat-item:last-child { border-right: none; }
  214. .stat-item:hover { background: rgba(201,168,76,0.08); }
  215. .stat-num {
  216. font-family: 'Playfair Display', serif;
  217. font-size: 2rem;
  218. font-weight: 700;
  219. color: var(--gold);
  220. display: block;
  221. }
  222. .stat-label {
  223. font-size: 0.75rem;
  224. letter-spacing: 0.12em;
  225. text-transform: uppercase;
  226. color: rgba(255,255,255,0.45);
  227. margin-top: 0.3rem;
  228. }
  229. /* ─── SECTION HEADING ────────────────────────────────── */
  230. .section-header {
  231. text-align: center;
  232. padding: 5rem 2rem 3rem;
  233. }
  234. .section-tag {
  235. display: inline-block;
  236. font-size: 0.7rem;
  237. font-weight: 600;
  238. letter-spacing: 0.35em;
  239. text-transform: uppercase;
  240. color: var(--gold);
  241. margin-bottom: 1rem;
  242. padding: 0.35rem 1rem;
  243. border: 1px solid var(--gold-light);
  244. background: rgba(201,168,76,0.06);
  245. }
  246. .section-title {
  247. font-family: 'Playfair Display', serif;
  248. font-size: clamp(1.8rem, 4vw, 2.8rem);
  249. font-weight: 700;
  250. color: var(--navy);
  251. line-height: 1.2;
  252. }
  253. .section-title em {
  254. font-style: italic;
  255. color: var(--accent);
  256. }
  257. .section-divider {
  258. width: 60px;
  259. height: 3px;
  260. background: var(--gold);
  261. margin: 1.5rem auto 0;
  262. }
  263. .section-sub {
  264. max-width: 520px;
  265. margin: 1.2rem auto 0;
  266. color: var(--text-muted);
  267. font-size: 0.95rem;
  268. line-height: 1.7;
  269. }
  270. /* ─── CHARTS SECTION ─────────────────────────────────── */
  271. .charts-section {
  272. background: var(--cream);
  273. padding-bottom: 5rem;
  274. }
  275. .charts-grid {
  276. display: grid;
  277. grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  278. gap: 1.5rem;
  279. padding: 0 4vw 2rem;
  280. max-width: 1400px;
  281. margin: 0 auto;
  282. }
  283. .chart-card {
  284. background: var(--white);
  285. border: 1px solid rgba(0,0,0,0.06);
  286. padding: 1.5rem 1rem 1.25rem;
  287. text-align: center;
  288. transition: all 0.35s ease;
  289. position: relative;
  290. overflow: hidden;
  291. }
  292. .chart-card::before {
  293. content: '';
  294. position: absolute;
  295. top: 0; left: 0; right: 0;
  296. height: 3px;
  297. background: linear-gradient(90deg, var(--gold), var(--accent));
  298. transform: scaleX(0);
  299. transition: transform 0.35s ease;
  300. }
  301. .chart-card:hover {
  302. transform: translateY(-6px);
  303. box-shadow: 0 20px 48px rgba(10,22,40,0.10);
  304. }
  305. .chart-card:hover::before { transform: scaleX(1); }
  306. .chart-card canvas {
  307. max-width: 180px;
  308. margin: 0 auto;
  309. display: block;
  310. }
  311. /* ─── FOOTER ACCENT ──────────────────────────────────── */
  312. .page-footer-accent {
  313. background: var(--navy);
  314. text-align: center;
  315. padding: 2rem;
  316. color: rgba(255,255,255,0.35);
  317. font-size: 0.8rem;
  318. letter-spacing: 0.1em;
  319. }
  320. .page-footer-accent span { color: var(--gold); }
  321. /* ─── RESPONSIVE ─────────────────────────────────────── */
  322. @media (max-width: 768px) {
  323. .stats-bar { grid-template-columns: repeat(2, 1fr); }
  324. .hero-content { padding: 0 5vw; }
  325. .hero-prev { left: 0.75rem; }
  326. .hero-next { right: 0.75rem; }
  327. }
  328. @media (max-width: 480px) {
  329. .stats-bar { grid-template-columns: 1fr 1fr; }
  330. .charts-grid { grid-template-columns: 1fr 1fr; gap: 1rem; }
  331. }
  332. </style>
  333. {% endblock %}
  334. {% block body %}
  335. {# ── HERO CAROUSEL ────────────────────────────────────────── #}
  336. <div id="heroCarousel" class="hero-slider">
  337. {# Slide 1 #}
  338. <div class="carousel-item-custom active"
  339. style="background-image:url({{ asset('assets/images/slider-01.jpg') }});">
  340. <div class="hero-overlay"></div>
  341. <div class="hero-content">
  342. <p class="hero-label">Excellence · Innovation · Bilingual Education</p>
  343. <h1 class="hero-title">
  344. {{ french_school_name }}<br>
  345. <em>{{ english_school_name }}</em>
  346. </h1>
  347. <p class="hero-sub">{{ french_slogan }} &nbsp;·&nbsp; {{ english_slogan }}</p>
  348. <div class="hero-cta">
  349. <a href="#officialExams" class="btn-gold">Voir les résultats</a>
  350. <a href="#" class="btn-outline-white">En savoir plus</a>
  351. </div>
  352. </div>
  353. </div>
  354. {# Slide 2 #}
  355. <div class="carousel-item-custom"
  356. style="background-image:url({{ asset('assets/images/slider-02.jpg') }});">
  357. <div class="hero-overlay"></div>
  358. <div class="hero-content">
  359. <p class="hero-label">Digital · Connected · Modern</p>
  360. <h1 class="hero-title">
  361. <em>LiveEdu</em><br>
  362. Software Online Services
  363. </h1>
  364. <p class="hero-sub">A complete digital ecosystem built for educators, students, and administrators.</p>
  365. <div class="hero-cta">
  366. <a href="#" class="btn-gold">Découvrir la plateforme</a>
  367. </div>
  368. </div>
  369. </div>
  370. {# Slide 3 #}
  371. <div class="carousel-item-custom"
  372. style="background-image:url({{ asset('assets/images/slide_04.PNG') }});">
  373. <div class="hero-overlay"></div>
  374. <div class="hero-content">
  375. <p class="hero-label">Transparency · Quality · Trust</p>
  376. <h1 class="hero-title">
  377. <em>{{ english_school_name }}</em><br>
  378. {{ english_slogan }}
  379. </h1>
  380. <p class="hero-sub">Real-time data, open reporting and trusted results — for every student, every year.</p>
  381. <div class="hero-cta">
  382. <a href="#officialExams" class="btn-gold">Voir les statistiques</a>
  383. </div>
  384. </div>
  385. </div>
  386. {# Decorative bar #}
  387. <div class="hero-bar"></div>
  388. {# Indicators #}
  389. <ol class="hero-indicators" id="heroIndicators">
  390. <li class="active" data-slide="0"></li>
  391. <li data-slide="1"></li>
  392. <li data-slide="2"></li>
  393. </ol>
  394. {# Slide counter #}
  395. <div class="slide-counter">
  396. <span id="slideNum">01</span> / 03
  397. </div>
  398. {# Controls #}
  399. <a class="hero-prev" id="heroPrev" href="#">
  400. <i class="fa fa-angle-left"></i>
  401. </a>
  402. <a class="hero-next" id="heroNext" href="#">
  403. <i class="fa fa-angle-right"></i>
  404. </a>
  405. </div>
  406. {# ── STATS BAR ─────────────────────────────────────────────── #}
  407. <div class="stats-bar">
  408. <div class="stat-item">
  409. <span class="stat-num">98%</span>
  410. <span class="stat-label">Taux d'admission</span>
  411. </div>
  412. <div class="stat-item">
  413. <span class="stat-num">400+</span>
  414. <span class="stat-label">Élèves inscrits</span>
  415. </div>
  416. <div class="stat-item">
  417. <span class="stat-num">50+</span>
  418. <span class="stat-label">Enseignants qualifiés</span>
  419. </div>
  420. <div class="stat-item">
  421. <span class="stat-num">{{ year.code }}</span>
  422. <span class="stat-label">Année académique</span>
  423. </div>
  424. </div>
  425. {# ── EXAM RESULTS SECTION ─────────────────────────────────── #}
  426. <section class="charts-section" id="officialExams">
  427. <div class="section-header">
  428. <span class="section-tag">Résultats officiels</span>
  429. <h2 class="section-title">
  430. Taux de réussite aux examens<br>
  431. session <em>{{ year.code }}</em>
  432. </h2>
  433. <div class="section-divider"></div>
  434. <p class="section-sub">
  435. Statistiques détaillées par série et par niveau pour la session officielle en cours.
  436. </p>
  437. </div>
  438. <div class="charts-grid">
  439. {% for key in results|keys %}
  440. <div class="chart-card">
  441. <canvas id="{{ key }}" height="160"
  442. data-exam-objects="{{ results[key] }}"></canvas>
  443. </div>
  444. {% endfor %}
  445. </div>
  446. </section>
  447. {# ── FOOTER ACCENT ─────────────────────────────────────────── #}
  448. <div class="page-footer-accent">
  449. Propulsé par <span>LiveEdu</span> · Tous droits réservés {{ "now"|date("Y") }}
  450. </div>
  451. {% endblock %}
  452. {% block javascripts %}
  453. {{ parent() }}
  454. <script>
  455. /* ── Custom Carousel ───────────────────────────────────────── */
  456. (function () {
  457. const slides = document.querySelectorAll('.carousel-item-custom');
  458. const indicators = document.querySelectorAll('#heroIndicators li');
  459. const slideNum = document.getElementById('slideNum');
  460. let current = 0, timer;
  461. function goTo(n) {
  462. slides[current].classList.remove('active');
  463. indicators[current].classList.remove('active');
  464. current = (n + slides.length) % slides.length;
  465. slides[current].classList.add('active');
  466. indicators[current].classList.add('active');
  467. slideNum.textContent = String(current + 1).padStart(2, '0');
  468. }
  469. function autoPlay() { timer = setInterval(() => goTo(current + 1), 5500); }
  470. function resetTimer() { clearInterval(timer); autoPlay(); }
  471. document.getElementById('heroPrev').addEventListener('click', e => {
  472. e.preventDefault(); goTo(current - 1); resetTimer();
  473. });
  474. document.getElementById('heroNext').addEventListener('click', e => {
  475. e.preventDefault(); goTo(current + 1); resetTimer();
  476. });
  477. indicators.forEach(li => {
  478. li.addEventListener('click', () => { goTo(+li.dataset.slide); resetTimer(); });
  479. });
  480. autoPlay();
  481. })();
  482. /* ── Charts ─────────────────────────────────────────────────── */
  483. const palette = [
  484. '#C9A84C','#2C6BAD','#1D8A6E','#D9534F',
  485. '#7B5EA7','#F0A500','#2E86AB','#A23B72'
  486. ];
  487. const randomColor = (type, idx) =>
  488. type === 'ECHEC' ? '#D9534F' : palette[idx % palette.length];
  489. const drawCanvas = (examData, canvasId, name) => {
  490. const el = document.getElementById(canvasId);
  491. if (!el || !examData) return;
  492. const parsed = JSON.parse(examData);
  493. const values = parsed.mentionCountCategories.map(Number);
  494. const colors = parsed.mentionCategories.map((cat, i) => randomColor(cat, i));
  495. new Chart(el, {
  496. type: 'doughnut',
  497. data: {
  498. labels: parsed.mentionCategories,
  499. datasets: [{ data: values, backgroundColor: colors, borderWidth: 0 }]
  500. },
  501. options: {
  502. cutout: '68%',
  503. animation: { animateRotate: true, duration: 1000 },
  504. plugins: {
  505. legend: { display: false },
  506. title: {
  507. display: true,
  508. text: name,
  509. color: '#0A1628',
  510. font: { size: 13, family: "'DM Sans', sans-serif", weight: '600' },
  511. position: 'bottom',
  512. padding: { top: 14 }
  513. }
  514. }
  515. }
  516. });
  517. };
  518. {% for key in results|keys %}
  519. drawCanvas(
  520. document.getElementById('{{ key }}')?.dataset?.examObjects,
  521. '{{ key }}',
  522. '{{ key|replace({'_': ' '})|title }}'
  523. );
  524. {% endfor %}
  525. </script>
  526. {% endblock javascripts %}