Files
alrahma_web_client/src/pages/HomePage.tsx
T
2026-04-25 00:00:10 -04:00

425 lines
19 KiB
TypeScript
Raw 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.
import { useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import { fetchAdministratorDashboardMetrics } from '../api/session'
import type { AdministratorDashboardMetricsResponse, AuthUser } from '../api/types'
import { useAuth } from '../auth/AuthProvider'
import './HomePage.css'
/** Public home must not call administrator APIs unless the user is allowed (avoids 401 for teachers/guests). */
function userMayLoadAdministratorHomeMetrics(user: AuthUser | null): boolean {
if (!user?.roles) return false
const r = user.roles
return Boolean(r.administrator || r.admin || r.super_admin)
}
/** Carousel + sections ported from CodeIgniter `Views/index.php` (Al Rahma public home). */
const CAROUSEL_SLIDES = [
{
image: '/images/carousel-1.png',
alt: 'Not only a book to be read but a guide illuminating our lives.',
title: 'Not only a book to be read but a guide illuminating our lives.',
body:
'At Al Rahma Sunday School, we teach the Quran as a living guide, nurturing love and respect for the words of Allah (SWT). Our program supports each childs journey through recitation, memorization, and age-appropriate translation and understanding.',
},
{
image: '/images/carousel-0.png',
alt: 'Faith and Knowledge Hand in Hand',
title: 'Faith and Knowledge Hand in Hand',
body:
'Our Sunday School program (Grades 1-9, Youth) is evenly divided between Islamic Studies in English—exploring topics about Allah, Islamic values, Muslim life and lessons from the Prophets—and Quran/Arabic studies focused on recitation, memorization and language. This balanced approach nurtures both understanding and practice of Islam.',
},
{
image: '/images/carousel-3.png',
alt: 'Nurturing Hearts and Minds',
title: 'Nurturing Hearts and Minds',
body:
'At our school, we inspire a lifelong love for Islamic values, for our worship rituals and our prophets through engaging lessons, interactive activities, and a supportive environment. Every student grows in knowledge, faith and character, learning to live the teachings of Islam in everyday life.',
},
{
image: '/images/carousel-4.png',
alt: 'Exciting Fun, Inside and Out!',
title: 'Exciting Fun, Inside and Out!',
body:
'From festive Eid celebrations to adventurous outdoor outings, our school events bring learning, laughter, and unforgettable memories together.',
},
{
image: '/images/carousel-5.png',
alt: 'Strengthening Faith, Character, and Community Bonds',
title: 'Strengthening Faith, Character, and Community Bonds',
body:
'A warm, faith-centered community helps children thrive, build confidence, compassion, and friendships.',
},
] as const
const STAT_DEF = [
{ key: 'students', label: 'Students', circle: 'circle-primary', icon: 'bi-mortarboard' },
{ key: 'teachers', label: 'Teachers', circle: 'circle-info', icon: 'bi-person-video3' },
{ key: 'teacherAssistants', label: 'TAs', circle: 'circle-success', icon: 'bi-person-gear' },
{ key: 'admins', label: 'Admins', circle: 'circle-warning', icon: 'bi-shield-check' },
{ key: 'parents', label: 'Parents', circle: 'circle-light', icon: 'bi-people' },
] as const
type CountKey = (typeof STAT_DEF)[number]['key']
function formatStat(
n: number | undefined,
numberFmt: Intl.NumberFormat,
): string {
return typeof n === 'number' && Number.isFinite(n) ? numberFmt.format(n) : '—'
}
export function HomePage() {
const { token, user } = useAuth()
const numberFmt = useMemo(() => new Intl.NumberFormat(), [])
const [counts, setCounts] = useState<AdministratorDashboardMetricsResponse['counts']>({})
const [showTop, setShowTop] = useState(false)
const mayLoadMetrics = Boolean(token && userMayLoadAdministratorHomeMetrics(user))
useEffect(() => {
if (!mayLoadMetrics) {
setCounts({})
return
}
let cancelled = false
const loadStats = async () => {
try {
const data = await fetchAdministratorDashboardMetrics()
if (!cancelled) setCounts(data.counts ?? {})
} catch {
if (!cancelled) setCounts({})
}
}
void loadStats()
const interval = window.setInterval(() => void loadStats(), 60_000)
const onVisibility = () => {
if (document.visibilityState === 'visible') void loadStats()
}
document.addEventListener('visibilitychange', onVisibility)
return () => {
cancelled = true
window.clearInterval(interval)
document.removeEventListener('visibilitychange', onVisibility)
}
}, [mayLoadMetrics])
useEffect(() => {
const onScroll = () => setShowTop(window.scrollY > 100)
window.addEventListener('scroll', onScroll, { passive: true })
onScroll()
return () => window.removeEventListener('scroll', onScroll)
}, [])
function countFor(key: CountKey): string {
return formatStat(counts?.[key], numberFmt)
}
return (
<div className="home-landing flex-grow-1">
<div
id="homeMainCarousel"
className="carousel slide carousel-fade home-carousel"
data-bs-ride="carousel"
>
<div className="carousel-indicators">
{CAROUSEL_SLIDES.map((_, i) => (
<button
key={i}
type="button"
data-bs-target="#homeMainCarousel"
data-bs-slide-to={i}
className={i === 0 ? 'active' : undefined}
aria-current={i === 0 ? 'true' : undefined}
aria-label={`Slide ${i + 1}`}
/>
))}
</div>
<div className="carousel-inner">
{CAROUSEL_SLIDES.map((slide, i) => (
<div key={slide.image} className={`carousel-item${i === 0 ? ' active' : ''}`}>
<img src={slide.image} className="d-block w-100" alt={slide.alt} />
<div className="carousel-caption">
<h2 className="mb-3">{slide.title}</h2>
<p className="mb-0">{slide.body}</p>
</div>
</div>
))}
</div>
<button
className="carousel-control-prev"
type="button"
data-bs-target="#homeMainCarousel"
data-bs-slide="prev"
>
<span className="carousel-control-prev-icon" aria-hidden />
<span className="visually-hidden">Previous</span>
</button>
<button
className="carousel-control-next"
type="button"
data-bs-target="#homeMainCarousel"
data-bs-slide="next"
>
<span className="carousel-control-next-icon" aria-hidden />
<span className="visually-hidden">Next</span>
</button>
</div>
<section className="text-center my-3">
<a
href="/account_creation_guide.pdf"
target="_blank"
rel="noopener noreferrer"
className="text-decoration-none"
style={{ fontWeight: 900, color: '#000' }}
>
<h3 className="fw-bold my-0">
<span className="text-decoration-underline">
Join Al Rahma family today! Click here for a quick guide on how to create an account.
</span>
</h3>
</a>
</section>
<div className="container-xxl py-3 home-section-xl content-section">
<div className="container">
<div className="home-stats">
<h2 className="d-flex justify-content-center p-md-1 fs-3 fw-bold green-title mb-0">
Active Participants
</h2>
<br />
<div className="stats-row">
{STAT_DEF.map((s) => (
<div key={s.key} className={`stat-circle ${s.circle}`}>
<div className="stat-icon">
<i className={`bi ${s.icon}`} aria-hidden />
</div>
<div className="stat-value">{countFor(s.key)}</div>
<div className="stat-title">{s.label}</div>
</div>
))}
</div>
</div>
</div>
</div>
<div className="container-xxl py-3 home-section-xl content-section">
<div className="container">
<div className="row bg-light squared align-items-center g-0">
<div className="col-lg-6">
<div className="d-flex flex-column justify-content-center p-4 p-md-5">
<h2 className="mb-4 fs-2 fw-bold green-title">
Faith, Education and Community for Over 30 Years
</h2>
<p className="mb-4">
The Islamic Society of Greater Lowell (ISGL), established in 1993 in Chelmsford,
Massachusetts, serves as both a mosque and a vibrant community center. It provides a
place of worship for Allah (SWT), offers Islamic education and facilitates religious
and social activities for Muslims in the Merrimack Valley. As a non-profit,
charitable, and tax-exempt organization, ISGL also provides essential services such as
marriage ceremonies, burial arrangements and community support while promoting a
greater understanding of Islam in America.
</p>
<p className="mb-4">
Under the umbrella of ISGL, Al Rahma Sunday School has been serving the community for
over thirty years. Throughout the decades, it has provided students with a strong
foundation in Islamic Studies and Quran, fostering both knowledge and character. With
its dedicated teachers and well-rounded academic program, the school continues to
guide generations of Muslim youth in their faith, values and practice of Islam.
</p>
<p>For more information, click below to visit ISGL official website.</p>
<div>
<a
className="btn btn-home-cta px-4 py-2 fw-semibold"
href="https://isgl.org"
target="_blank"
rel="noopener noreferrer"
>
ISGL Official Website
</a>
</div>
</div>
</div>
<div className="col-lg-6 image-column pe-lg-3">
<div className="position-relative h-100 w-100">
<img
className="w-100 h-100 rounded-end"
src="/images/isgl_home.png"
alt="ISGL"
style={{ objectFit: 'cover', minHeight: 280 }}
onError={(e) => {
const img = e.currentTarget
img.onerror = null
img.src = '/images/call-to-action.jpg'
}}
/>
</div>
</div>
</div>
</div>
</div>
<div className="container-xxl py-3 home-section-xl content-section">
<div className="container">
<div className="row bg-light squared align-items-center g-0">
<div className="col-lg-6">
<div className="d-flex flex-column justify-content-center p-4 p-md-5">
<h2 className="mb-4 fs-2 fw-bold green-title">Our Mission</h2>
<p>
Al Rahma Sunday School&apos;s mission is to make the Masjid a central part of our
Muslim children&apos;s lives from a very young age. We are dedicated to offering a
strong, well-rounded curriculum in Quran, Arabic and Islamic Studies. Our goal is to
deliver the highest quality education to help instill Islamic values, beliefs and
practices in each student. Additionally, we regularly organize engaging and fun events
throughout the year to make the learning experience more enjoyable and spiritually
enriching.
</p>
<p className="mb-0">
We deeply appreciate your continued support and cooperation in helping us fulfill this
mission. Together, we can provide a strong Islamic foundation for our children and shape
a future generation that is confident in their faith and rooted in Islamic values.
</p>
</div>
</div>
<div className="col-lg-6 about-img py-4 py-lg-0">
<div className="row g-2 justify-content-center">
<div className="col-12 text-center">
<img
className="img-fluid w-75 rounded-circle bg-light p-3"
src="/images/about-1.jpg"
alt=""
/>
</div>
<div className="col-6 text-start" style={{ marginTop: '-150px' }}>
<img
className="img-fluid w-100 rounded-circle bg-light p-3"
src="/images/about-2.jpg"
alt=""
/>
</div>
<div className="col-6 text-end" style={{ marginTop: '-150px' }}>
<img
className="img-fluid w-100 rounded-circle bg-light p-3"
src="/images/about-3.jpg"
alt=""
/>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="container-xxl py-3 home-section-xl content-section">
<div className="container">
<div className="row bg-light squared align-items-center g-0">
<div className="col-lg-6">
<div className="d-flex flex-column justify-content-center p-4 p-md-5">
<h2 className="mb-4 fs-2 fw-bold green-title">Become A Teacher or Admin</h2>
<p className="mb-4">
Volunteering at Al Rahma Sunday School is a deeply fulfilling way to give back to the
community and help shape the next generation. Whether you&apos;re passionate about
teaching or prefer working behind the scenes, your time and dedication can make a
lasting difference. Join a team committed to nurturing young minds and strengthening
their connection to faith.
</p>
<p className="mb-4">
As a volunteer teacher or teacher assistant, you&apos;ll have the opportunity to
inspire, educate, and guide children on their spiritual journey. Teachers play a vital
role in helping students understand the Quran, Islamic values, and the Arabic language
in a warm and engaging classroom environment. Teacher assistants support instruction,
help manage classroom activities, and provide one-on-one assistance to students when
needed. Whether leading the class or lending a helping hand, your commitment can
spark a lifelong love for learning and faith in the hearts of our students.
</p>
<p className="mb-4">
Administrative volunteers are essential to the success of our school. From organizing
materials and managing communications to helping coordinate school events and
logistics, your work ensures a smooth and efficient learning experience for students
and teachers alike. If you enjoy structured tasks, planning, or simply being helpful
in a quiet but powerful way, this role is perfect for you.
</p>
<div>
<Link className="btn btn-home-cta py-3 px-5 mt-1" to="/register">
Get Started Now <i className="bi bi-arrow-right ms-2" aria-hidden />
</Link>
</div>
</div>
</div>
<div className="col-lg-6 image-column pe-lg-3">
<div className="position-relative h-100 w-100">
<img
className="w-100 h-100 rounded-end"
src="/images/call-to-action.jpg"
alt=""
style={{ objectFit: 'cover', minHeight: 280 }}
onError={(e) => {
const img = e.currentTarget
img.onerror = null
img.src = '/images/isgl_home.png'
}}
/>
</div>
</div>
</div>
</div>
</div>
<div className="container-xxl py-3 home-section-xl content-section">
<div className="container">
<div className="row bg-light squared position-relative align-items-center g-0">
<div className="col-lg-6">
<div className="h-100 d-flex flex-column justify-content-center p-4 p-md-5">
<h2 className="mb-4 fs-2 fw-bold green-title">Our Curriculum and Grade Structure</h2>
<p>
Our program spans nine structured grade levels, each building upon the previous
year&apos;s knowledge to ensure a solid foundation in faith, character, and Islamic
learning.
</p>
<p>
Upon completing the 9th grade, students transition into our three-year Youth Program,
which emphasizes deeper community engagement, personal development and practical
application of Islamic principles. Participation in the Youth Program requires students
to be at least 15 years old, ensuring they are mature enough to benefit from its
advanced content.
</p>
<p>
Starting this academic year, children must be at least 6 years old by 12-31-2025 to
enroll in Grade 1. For younger learners, we are pleased to offer our newly established
Kindergarten class, welcoming children who are at least 5 years old by 12-31-2025. This
early education program is designed to introduce young minds to the basics of Islamic
teachings in a warm, age-appropriate environment.
</p>
<div>
<Link className="btn btn-home-cta py-3 px-5 mt-3" to="/register">
Get Started Now <i className="bi bi-arrow-right ms-2" aria-hidden />
</Link>
</div>
</div>
</div>
<div className="col-lg-6 text-start py-4 py-lg-0">
<div className="image-container mx-auto mx-lg-0">
<img
src="/images/12.jpeg"
className="overlapping-image image1"
alt="Students and activities"
/>
</div>
</div>
</div>
</div>
</div>
<button
type="button"
className={`btn btn-home-cta btn-lg rounded-1 back-to-top${showTop ? ' visible' : ''}`}
aria-label="Back to top"
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
>
<i className="bi bi-arrow-up" aria-hidden />
</button>
</div>
)
}