Files
root 1d964c79de
Deploy to Shared Hosting / Shared hosting deploy (push) Failing after 48s
Tests / PHPUnit (push) Successful in 1m22s
fix banner time
2026-09-03 00:05:44 -04:00

850 lines
32 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Al Rahma Sunday School</title>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="Al Rahma Sunday School — Quran, Arabic and Islamic Studies for children in the Merrimack Valley" name="description">
<!-- Bootstrap CSS -->
<link href="<?= base_url('assets/boot_css/bootstrap.min.css') ?>" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Google Web Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Amiri:wght@400;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Icon Font Stylesheet -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css" rel="stylesheet">
<style>
:root {
--ink: #16262B;
--ink-soft: #3E4E51;
--paper: #F3EFE3;
--paper-deep: #E9E3D2;
--sage: #E7EEE6;
--primary: #0B5D52;
--primary-dark: #073F38;
--accent: #C6963C;
--accent-soft: #EFE1BC;
--line: rgba(22, 38, 43, 0.12);
}
* {
box-sizing: border-box;
}
body {
font-family: 'Inter', sans-serif;
color: var(--ink);
overflow-x: hidden;
margin: 0;
background-color: var(--paper);
line-height: 1.6;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Amiri', serif;
font-weight: 700;
color: var(--ink);
line-height: 1.2;
margin: 0 0 1rem;
}
p {
color: var(--ink-soft);
max-width: 62ch;
}
a {
color: var(--primary);
}
.btn-brand {
display: inline-flex;
align-items: center;
gap: 0.6rem;
background-color: var(--primary);
color: #fff;
border: none;
border-radius: 2px;
padding: 0.85rem 1.75rem;
font-weight: 600;
font-size: 0.95rem;
text-decoration: none;
transition: background-color 0.2s ease;
}
.btn-brand:hover {
background-color: var(--primary-dark);
color: #fff;
}
.btn-brand-outline {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border: 1.5px solid var(--ink);
color: var(--ink);
border-radius: 999px;
padding: 0.5rem 1.25rem;
font-weight: 600;
font-size: 0.9rem;
text-decoration: none;
}
.btn-brand-outline:hover {
background-color: var(--ink);
color: var(--paper);
}
.btn-brand-danger {
display: inline-flex;
align-items: center;
gap: 0.5rem;
border: 1.5px solid #a33;
color: #a33;
border-radius: 999px;
padding: 0.5rem 1.25rem;
font-weight: 600;
font-size: 0.9rem;
text-decoration: none;
}
.btn-brand-danger:hover {
background-color: #a33;
color: #fff;
}
.rule {
width: 56px;
height: 3px;
background-color: var(--accent);
border: none;
margin: 0 0 1.5rem;
}
/* Navbar */
.navbar {
background-color: var(--paper) !important;
border-bottom: 1px solid var(--line);
padding-top: 0.6rem;
padding-bottom: 0.6rem;
}
.navbar-text {
color: var(--ink-soft);
font-size: 0.9rem;
}
/* Hero / carousel */
.hero-wrap {
position: relative;
background-color: var(--primary-dark);
}
.hero-wrap::before {
content: "";
position: absolute;
inset: 0;
opacity: 0.16;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='84' height='84' viewBox='0 0 84 84'%3E%3Cg fill='none' stroke='%23C6963C' stroke-width='1'%3E%3Cpath d='M42 2 L62 22 L42 42 L22 22 Z'/%3E%3Cpath d='M0 42 L20 22 L40 42 L20 62 Z'/%3E%3Cpath d='M42 42 L62 22 L84 42 L62 62 Z'/%3E%3Cpath d='M42 42 L62 62 L42 84 L22 62 Z'/%3E%3C/g%3E%3C/svg%3E");
background-size: 84px 84px;
pointer-events: none;
}
.carousel-item {
height: 560px;
overflow: hidden;
}
.carousel-item img {
object-fit: cover;
height: 100%;
width: 100%;
opacity: 0.82;
}
.carousel-caption {
position: absolute;
bottom: 12%;
left: 8%;
right: auto;
text-align: left;
padding: 2rem 2.25rem;
background: var(--primary-dark);
border-left: 4px solid var(--accent);
max-width: 560px;
}
.carousel-caption h1 {
font-size: 2rem;
color: #fff !important;
margin-bottom: 0.75rem;
}
.carousel-caption p {
font-size: 1rem;
color: #EDE7D6 !important;
margin-bottom: 0;
max-width: none;
}
.carousel-indicators [data-bs-target] {
background-color: var(--accent);
}
/* Open positions banner */
.careers-ticker {
display: block;
background-color: var(--primary-dark);
color: var(--paper);
text-decoration: none;
overflow: hidden;
border-top: 1px solid rgba(243, 239, 227, 0.14);
border-bottom: 1px solid rgba(243, 239, 227, 0.14);
}
.careers-ticker:hover,
.careers-ticker:focus {
color: var(--paper);
}
.ticker-track {
display: flex;
width: max-content;
animation: ticker-scroll 60s linear infinite;
will-change: transform;
}
.ticker-sequence {
display: flex;
flex: 0 0 auto;
}
.careers-ticker:hover .ticker-track,
.careers-ticker:focus .ticker-track,
.careers-ticker:focus-within .ticker-track {
animation-play-state: paused;
}
.ticker-group {
display: flex;
align-items: center;
flex: 0 0 auto;
min-width: max-content;
}
.ticker-label,
.ticker-item {
display: inline-flex;
align-items: center;
min-height: 54px;
white-space: nowrap;
}
.ticker-label {
padding: 0 1.5rem;
font-weight: 700;
color: var(--accent-soft);
}
.ticker-item {
gap: 0.5rem;
padding: 0 1.75rem;
border-left: 1px solid rgba(243, 239, 227, 0.16);
}
.ticker-title {
font-weight: 700;
}
.ticker-meta {
color: #DCE6DD;
font-size: 0.9rem;
}
@keyframes ticker-scroll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
@media (max-width: 992px) {
.carousel-item { height: 480px; }
.carousel-caption { max-width: 78%; padding: 1.5rem; bottom: 8%; }
.carousel-caption h1 { font-size: 1.5rem; }
}
@media (max-width: 576px) {
.carousel-item { height: 400px; }
.carousel-caption { left: 5%; right: 5%; max-width: none; padding: 1.1rem 1.25rem; bottom: 6%; }
.carousel-caption h1 { font-size: 1.2rem; }
.carousel-caption p { font-size: 0.85rem; }
.ticker-track { animation-duration: 75s; }
.ticker-label, .ticker-item { min-height: 48px; }
.ticker-item { padding: 0 1.25rem; }
}
/* Join line */
.join-strip {
background-color: var(--sage);
border-bottom: 1px solid var(--line);
padding: 0.9rem 0;
text-align: center;
}
.join-strip a {
color: var(--primary-dark);
font-weight: 600;
text-decoration: none;
border-bottom: 1px solid var(--accent);
}
/* Section rhythm */
.section {
padding: 4.5rem 0;
}
.section-tight {
padding: 3rem 0;
}
.container-narrow {
max-width: 1160px;
margin: 0 auto;
padding: 0 1.25rem;
}
/* Stats band */
.stats-band {
background-color: var(--ink);
color: var(--paper);
}
.stats-band h2 {
color: var(--paper);
font-size: 1.6rem;
text-align: center;
margin-bottom: 2.5rem;
}
.stats-row {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.stat-cell {
flex: 1 1 160px;
text-align: center;
padding: 0 1.5rem;
border-left: 1px solid rgba(243, 239, 227, 0.18);
}
.stat-cell:first-child {
border-left: none;
}
.stat-value {
font-family: 'Amiri', serif;
font-size: 2.75rem;
font-weight: 700;
color: var(--accent);
line-height: 1;
}
.stat-title {
margin-top: 0.6rem;
font-size: 0.85rem;
letter-spacing: 0.02em;
color: #CFC9B7;
}
@media (max-width: 768px) {
.stat-cell {
border-left: none;
border-top: 1px solid rgba(243, 239, 227, 0.18);
padding: 1.25rem 1rem 0;
flex: 1 1 45%;
}
.stat-cell:nth-child(1), .stat-cell:nth-child(2) {
border-top: none;
}
}
/* Alternating content blocks */
.story-block {
display: flex;
align-items: stretch;
gap: 3rem;
}
.story-block.reverse {
flex-direction: row-reverse;
}
.story-text {
flex: 1 1 50%;
display: flex;
flex-direction: column;
justify-content: center;
padding: 1rem 0;
}
.story-media {
flex: 1 1 50%;
position: relative;
min-height: 360px;
}
.story-media img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 2px;
}
.story-media::after {
content: "";
position: absolute;
width: 34px;
height: 34px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='34' viewBox='0 0 34 34'%3E%3Cpath fill='none' stroke='%23C6963C' stroke-width='2' d='M17 1 L27 9 L27 25 L17 33 L7 25 L7 9 Z'/%3E%3C/svg%3E");
background-size: contain;
background-repeat: no-repeat;
}
.story-block:not(.reverse) .story-media::after {
top: -14px;
right: -14px;
}
.story-block.reverse .story-media::after {
top: -14px;
left: -14px;
}
@media (max-width: 900px) {
.story-block, .story-block.reverse {
flex-direction: column;
gap: 1.5rem;
}
.story-media {
min-height: 260px;
}
}
@media (max-width: 576px) {
.section {
padding: 2.25rem 0;
}
.section-tight {
padding: 2rem 0;
}
.container-narrow {
padding: 0 1rem;
}
.stats-band h2 {
margin-bottom: 1.5rem;
}
.story-block, .story-block.reverse {
gap: 1.15rem;
}
.story-text {
padding: 0;
}
.story-text p:last-child {
margin-bottom: 0;
}
.story-media {
min-height: 220px;
}
.curriculum-image {
min-height: 220px;
}
}
/* Curriculum block */
.curriculum-section {
background-color: var(--sage);
}
.curriculum-image {
width: 100%;
height: 100%;
min-height: 340px;
object-fit: cover;
border-radius: 2px;
}
/* Site footer top edge motif */
.site-footer {
position: relative;
}
.site-footer::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 6px;
background-image: repeating-linear-gradient(135deg, var(--accent) 0 8px, transparent 8px 16px);
opacity: 0.6;
}
/* Back to top */
.back-to-top {
position: fixed;
bottom: 30px;
right: 30px;
z-index: 99;
display: none;
background-color: var(--primary);
border-color: var(--primary);
}
</style>
</head>
<body>
<!-- Navbar Start -->
<nav class="navbar navbar-expand-lg navbar-light sticky-top px-4 px-lg-5">
<a href="<?= base_url('/') ?>" class="navbar-brand d-flex align-items-center">
<img src="<?= base_url('images/logo.png') ?>" alt="Al Rahma Sunday School" style="height: 56px; width: 56px; border-radius: 50%; object-fit: contain; background-color: #fff;">
</a>
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbarCollapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<div class="navbar-nav mx-auto"></div>
<div class="d-flex align-items-center">
<?php if (session()->get('is_logged_in')): ?>
<span class="navbar-text me-3">
Welcome, <?= esc(session()->get('user_name')) ?>
</span>
<a href="<?= base_url('/dashboard') ?>" class="btn-brand-outline me-2">
Dashboard <i class="fa fa-tachometer-alt"></i>
</a>
<a href="<?= base_url('/logout') ?>" class="btn-brand-danger">
Logout <i class="fa fa-sign-out-alt"></i>
</a>
<?php else: ?>
<a href="<?= base_url('/login') ?>" class="btn-brand-outline me-2">
Login <i class="fa fa-arrow-right"></i>
</a>
<a href="<?= base_url('/register') ?>" class="btn-brand">
Register <i class="fa fa-arrow-right"></i>
</a>
<?php endif; ?>
</div>
</div>
</nav>
<!-- Navbar End -->
<!-- Carousel Start -->
<div class="hero-wrap">
<div id="mainCarousel" class="carousel slide carousel-fade" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="2" aria-label="Slide 3"></button>
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="3" aria-label="Slide 4"></button>
<button type="button" data-bs-target="#mainCarousel" data-bs-slide-to="4" aria-label="Slide 5"></button>
</div>
<div class="carousel-inner">
<!-- Slide 1 -->
<div class="carousel-item active">
<img src="<?= base_url('images/carousel-1.png') ?>" class="d-block w-100" alt="Not only a book to be read but a guide illuminating our lives.">
<div class="carousel-caption">
<h1>Not only a book to be read, but a guide illuminating our lives</h1>
<p>We teach the Quran as a living guide, nurturing love and respect for the words of Allah (SWT) through recitation, memorization and age-appropriate understanding.</p>
</div>
</div>
<!-- Slide 2 -->
<div class="carousel-item">
<img src="<?= base_url('images/carousel-0.png') ?>" class="d-block w-100" alt="Faith and Knowledge Hand in Hand">
<div class="carousel-caption">
<h1>Faith and knowledge, hand in hand</h1>
<p>Our program for Grades 110 and Youth splits evenly between Islamic Studies — Allah, Islamic values, and lessons from the Prophets — and Quran and Arabic recitation, memorization and language.</p>
</div>
</div>
<!-- Slide 3 -->
<div class="carousel-item">
<img src="<?= base_url('images/carousel-3.png') ?>" class="d-block w-100" alt="Nurturing Hearts and Minds">
<div class="carousel-caption">
<h1>Nurturing hearts and minds</h1>
<p>Engaging lessons and a supportive environment help every student grow in knowledge, faith and character, and learn to live Islam's teachings day to day.</p>
</div>
</div>
<!-- Slide 4 -->
<div class="carousel-item">
<img src="<?= base_url('images/carousel-4.png') ?>" class="d-block w-100" alt="Exciting Fun, Inside and Out!">
<div class="carousel-caption">
<h1>Exciting, inside and out</h1>
<p>From festive Eid celebrations to adventurous outdoor outings, our school events bring learning, laughter and memories together.</p>
</div>
</div>
<!-- Slide 5 -->
<div class="carousel-item">
<img src="<?= base_url('images/carousel-5.png') ?>" class="d-block w-100" alt="Strengthening Faith, Character, and Community Bonds">
<div class="carousel-caption">
<h1>Strengthening faith, character and community</h1>
<p>A warm, faith-centered community helps children build confidence, compassion and lasting friendships.</p>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#mainCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#mainCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
<!-- Carousel End -->
<?php
$tickerPositions = !empty($openPositions) && is_array($openPositions) ? $openPositions : [];
$tickerItems = [];
foreach ($tickerPositions as $position) {
$meta = array_filter([
$position['department'] ?? '',
$position['location'] ?? '',
$position['employment_type'] ?? '',
], static fn ($value) => trim((string) $value) !== '');
$tickerItems[] = [
'title' => (string) ($position['title'] ?? 'Open Position'),
'meta' => implode(' · ', $meta),
];
}
if ($tickerItems === []) {
$tickerItems[] = [
'title' => 'Volunteer opportunities',
'meta' => 'See current openings',
];
}
?>
<a class="careers-ticker" href="<?= site_url('careers') ?>" aria-label="View open volunteer positions">
<div class="ticker-track">
<?php for ($sequence = 0; $sequence < 2; $sequence++): ?>
<div class="ticker-sequence" <?= $sequence === 1 ? 'aria-hidden="true"' : '' ?>>
<?php for ($copy = 0; $copy < 4; $copy++): ?>
<div class="ticker-group" <?= $sequence === 0 && $copy === 0 ? '' : 'aria-hidden="true"' ?>>
<span class="ticker-label">Now recruiting volunteers</span>
<?php foreach ($tickerItems as $item): ?>
<span class="ticker-item">
<span class="ticker-title"><?= esc($item['title']) ?></span>
<?php if ($item['meta'] !== ''): ?>
<span class="ticker-meta"><?= esc($item['meta']) ?></span>
<?php endif; ?>
<i class="fa fa-arrow-right" aria-hidden="true"></i>
</span>
<?php endforeach; ?>
</div>
<?php endfor; ?>
</div>
<?php endfor; ?>
</div>
</a>
<!-- Join line -->
<div class="join-strip">
<a href="<?= base_url('account_creation_guide.pdf') ?>" target="_blank">
Join the Al Rahma family — see our quick guide to creating an account
</a>
</div>
<!-- Statistics Start -->
<div class="stats-band section-tight">
<div class="container-narrow" data-dashboard-endpoint="<?= site_url('api/administrator/dashboard') ?>">
<h2>Active Participants</h2>
<div class="stats-row">
<div class="stat-cell">
<div class="stat-value" data-stat="students">—</div>
<div class="stat-title">Students</div>
</div>
<div class="stat-cell">
<div class="stat-value" data-stat="teachers">—</div>
<div class="stat-title">Teachers</div>
</div>
<div class="stat-cell">
<div class="stat-value" data-stat="teacherAssistants">—</div>
<div class="stat-title">Teacher Assistants</div>
</div>
<div class="stat-cell">
<div class="stat-value" data-stat="admins">—</div>
<div class="stat-title">Admins</div>
</div>
<div class="stat-cell">
<div class="stat-value" data-stat="parents">—</div>
<div class="stat-title">Parents</div>
</div>
</div>
</div>
</div>
<!-- Statistics End -->
<!-- ISGL history -->
<div class="section">
<div class="container-narrow">
<div class="story-block">
<div class="story-text">
<hr class="rule">
<h2>Faith, education and community for over 30 years</h2>
<p>The Islamic Society of Greater Lowell (ISGL), established in 1993 in Chelmsford, Massachusetts, serves as both a mosque and a vibrant community center — a place of worship, Islamic education and religious and social life for Muslims across the Merrimack Valley. As a non-profit, charitable and tax-exempt organization, ISGL also provides marriage ceremonies, burial arrangements and community support, while promoting a greater understanding of Islam in America.</p>
<p>Under ISGL, Al Rahma Sunday School has served the community for over thirty years, giving students a strong foundation in Islamic Studies and Quran. Its dedicated teachers and well-rounded program continue to guide generations of Muslim youth in their faith, values and practice of Islam.</p>
<p><a class="btn-brand" href="https://isgl.org" target="_blank" rel="noopener noreferrer">Visit ISGL's website <i class="fa fa-arrow-right"></i></a></p>
</div>
<div class="story-media">
<img src="<?= base_url('images/isgl_home.png') ?>" alt="ISGL mosque and community center" onerror="this.onerror=null; this.src='<?= base_url('images/call-to-action.jpg') ?>';">
</div>
</div>
</div>
</div>
<!-- Our Mission -->
<div class="section" style="padding-top: 0;">
<div class="container-narrow">
<div class="story-block reverse">
<div class="story-text">
<hr class="rule">
<h2>Our mission</h2>
<p>Al Rahma Sunday School exists to make the Masjid a central part of our children's lives from a young age. We offer a strong, well-rounded curriculum in Quran, Arabic and Islamic Studies, aiming to instill Islamic values, beliefs and practices in every student — and we organize events throughout the year that make learning enjoyable and spiritually enriching.</p>
<p>We're grateful for your continued support and cooperation. Together, we can give our children a strong Islamic foundation and shape a future generation confident in their faith and rooted in Islamic values.</p>
</div>
<div class="story-media">
<img src="<?= base_url('images/about-1.jpg') ?>" alt="Students at Al Rahma Sunday School">
</div>
</div>
</div>
</div>
<!-- Become a Teacher or Admin -->
<div class="section" style="padding-top: 0;">
<div class="container-narrow">
<div class="story-block">
<div class="story-text">
<hr class="rule">
<h2>Become a teacher or admin</h2>
<p>Volunteering here is a fulfilling way to give back and help shape the next generation. As a teacher or teacher assistant, you'll help students understand the Quran, Islamic values and Arabic in a warm, engaging classroom — leading lessons, supporting instruction, or offering one-on-one help.</p>
<p>Administrative volunteers keep the school running smoothly: organizing materials, managing communications, and coordinating events and logistics. If structured, behind-the-scenes work suits you, this role is a strong fit.</p>
<p><a class="btn-brand" href="<?= base_url('/careers') ?>">See open positions <i class="fa fa-arrow-right"></i></a></p>
</div>
<div class="story-media">
<img src="<?= base_url('images/call-to-action.jpg') ?>" alt="Volunteer teachers and admins at Al Rahma" onerror="this.onerror=null; this.src='<?= base_url('images/call-to-action.jpg') ?>';">
</div>
</div>
</div>
</div>
<!-- Curriculum -->
<div class="section curriculum-section">
<div class="container-narrow">
<div class="story-block reverse" style="align-items: center;">
<div class="story-text">
<hr class="rule">
<h2>Our curriculum and grade structure</h2>
<p>Our program spans ten structured grade levels, each building on the last to give students a solid foundation in faith, character and Islamic learning.</p>
<p>After 10th grade, students move into our two-year Youth Program, focused on community engagement, personal development and the practical application of Islamic principles. Youth Program participants must be at least 16.</p>
<p>Starting this academic year, children must be at least 6 years old by September 1, 2026 to enroll in Grade 1. Younger learners are welcome in our new Kindergarten class, open to children who are at least 5 years old by December 31, 2026 — a warm, age-appropriate introduction to the basics of Islamic teaching.</p>
<p><a class="btn-brand" href="<?= base_url('/register') ?>">Get started now <i class="fa fa-arrow-right"></i></a></p>
</div>
<div class="story-media">
<img class="curriculum-image" src="<?= base_url('images/12.jpeg') ?>" alt="Students in class at Al Rahma Sunday School">
</div>
</div>
</div>
</div>
<!-- Footer Start -->
<?php include(__DIR__ . '/partials/footer.php'); ?>
<!-- Footer End -->
<!-- Back to Top -->
<a href="#" class="btn btn-lg btn-success btn-lg-square back-to-top"><i class="bi bi-arrow-up"></i></a>
<!-- JavaScript Libraries -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
$(document).ready(function () {
$(window).scroll(function () {
if ($(this).scrollTop() > 100) {
$('.back-to-top').fadeIn();
} else {
$('.back-to-top').fadeOut();
}
});
$('.back-to-top').click(function () {
$("html, body").animate({ scrollTop: 0 }, 600);
return false;
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const container = document.querySelector('.stats-band [data-dashboard-endpoint]');
if (!container) return;
const endpoint = container.dataset.dashboardEndpoint;
const statElements = container.querySelectorAll('[data-stat]');
const numberFormatter = new Intl.NumberFormat();
let isLoading = false;
const loadStats = function () {
if (isLoading) return;
isLoading = true;
fetch(endpoint, {
headers: { 'Accept': 'application/json' },
credentials: 'same-origin',
})
.then(function (response) {
if (!response.ok) throw new Error('Request failed');
return response.json();
})
.then(function (payload) {
const counts = payload && typeof payload === 'object' && payload.counts ? payload.counts : {};
statElements.forEach(function (element) {
const key = element.dataset.stat;
const value = Number(counts[key]);
element.textContent = Number.isFinite(value) ? numberFormatter.format(value) : '—';
});
})
.catch(function () {})
.finally(function () {
isLoading = false;
});
};
loadStats();
setInterval(loadStats, 60000);
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'visible') loadStats();
});
});
</script>
</body>
</html>