Align site copy and structure with client foundation brief
Add About, Mission, What We Do, Events, and Contact pages; update hero, footer, nav, EIN 33-4887159, and [email protected]; warm cream/beige palette and faith-centered messaging for LA County outreach. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+6
-6
@@ -7,21 +7,21 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Miracles In Motion | 501(c)3 Non-Profit Organization</title>
|
||||
<meta name="description" content="Miracles In Motion is a 501(c)3 non-profit organization dedicated to creating positive change in our community through compassionate action and support." />
|
||||
<title>Miracles in Motion Foundation | Faith • Hope • Community • Restoration</title>
|
||||
<meta name="description" content="Restoring hope through compassion, community, and faith. Serving Los Angeles County with outreach, emergency assistance, and advocacy for families in crisis." />
|
||||
<meta name="keywords" content="non-profit, charity, 501c3, miracles in motion, community support, donations, volunteers" />
|
||||
|
||||
<!-- Open Graph Meta Tags -->
|
||||
<meta property="og:title" content="Miracles In Motion | 501(c)3 Non-Profit Organization" />
|
||||
<meta property="og:description" content="Creating positive change in our community through compassionate action and support." />
|
||||
<meta property="og:title" content="Miracles in Motion Foundation" />
|
||||
<meta property="og:description" content="Restoring hope through compassion, community, and faith." />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://mim4u.org" />
|
||||
<meta property="og:image" content="/og-image.png" />
|
||||
|
||||
<!-- Twitter Card Meta Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="Miracles In Motion | 501(c)3 Non-Profit Organization" />
|
||||
<meta name="twitter:description" content="Creating positive change in our community through compassionate action and support." />
|
||||
<meta name="twitter:title" content="Miracles in Motion Foundation" />
|
||||
<meta name="twitter:description" content="Restoring hope through compassion, community, and faith." />
|
||||
<meta name="twitter:image" content="/og-image.png" />
|
||||
|
||||
<!-- Favicon and Web App Manifest -->
|
||||
|
||||
Binary file not shown.
@@ -35,6 +35,31 @@
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://mim4u.org/#/about</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://mim4u.org/#/mission</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://mim4u.org/#/what-we-do</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://mim4u.org/#/events</loc>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.7</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://mim4u.org/#/contact</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://mim4u.org/#/brand</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
|
||||
+87
-91
@@ -67,6 +67,16 @@ import MimChatAgent from './components/MimChatAgent'
|
||||
import { Navigation } from './components/Navigation'
|
||||
import { Footer } from './components/Footer'
|
||||
import { BrandAssetsPage } from './pages/BrandPage'
|
||||
import {
|
||||
AboutPage,
|
||||
ContactPage,
|
||||
EventsPage,
|
||||
MissionPage,
|
||||
StoriesIntroBlock,
|
||||
WhatWeDoPage,
|
||||
} from './pages/foundation'
|
||||
import { WhoWeServe } from './components/home/WhoWeServe'
|
||||
import { SITE, WHAT_WE_DO } from './content/siteContent'
|
||||
|
||||
/**
|
||||
* Miracles in Motion — Complete Non-Profit Website
|
||||
@@ -590,11 +600,6 @@ interface FeatureCardProps {
|
||||
body: string
|
||||
}
|
||||
|
||||
interface StatProps {
|
||||
label: string
|
||||
value: number
|
||||
}
|
||||
|
||||
interface SectionHeaderProps {
|
||||
eyebrow?: string
|
||||
title: string
|
||||
@@ -788,6 +793,7 @@ function HomePage() {
|
||||
return (
|
||||
<>
|
||||
<Hero />
|
||||
<WhoWeServe />
|
||||
<PartnerMarquee />
|
||||
<Programs />
|
||||
<Impact />
|
||||
@@ -813,7 +819,7 @@ function Hero() {
|
||||
<section ref={containerRef} className="relative isolate overflow-hidden min-h-screen flex items-center">
|
||||
{/* Enhanced 3D Background Layers */}
|
||||
<motion.div
|
||||
className="absolute inset-0 bg-gradient-to-br from-primary-50/30 via-white to-secondary-50/30 dark:from-gray-900/30 dark:via-gray-800/30 dark:to-gray-900/30"
|
||||
className="absolute inset-0 bg-gradient-to-br from-[var(--mim-cream)] via-white to-secondary-50/40 dark:from-gray-900/30 dark:via-gray-800/30 dark:to-gray-900/30"
|
||||
style={{ y: backgroundY }}
|
||||
>
|
||||
<FloatingParticles />
|
||||
@@ -846,19 +852,21 @@ function Hero() {
|
||||
>
|
||||
<div className="lg:col-span-7">
|
||||
<ParallaxContainer depth={0.3}>
|
||||
<p className="text-sm font-medium tracking-wide text-secondary-700 dark:text-secondary-300">
|
||||
{SITE.tagline}
|
||||
</p>
|
||||
<motion.h1
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="text-balance text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl transform-gpu"
|
||||
className="mt-3 text-balance font-serif text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl transform-gpu"
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
>
|
||||
Equipping kids for success—
|
||||
<span className="relative whitespace-pre gradient-text"> school supplies, clothing, & more</span>
|
||||
{SITE.brandMessage}
|
||||
</motion.h1>
|
||||
<p className="mt-5 max-w-xl text-lg leading-7 text-neutral-700 dark:text-neutral-300">
|
||||
Miracles in Motion is a nonprofit providing students with the essentials they need to thrive: backpacks and notebooks, uniforms and shoes, and the everything-else fund for urgent needs.
|
||||
Bringing hope, compassion, and support to individuals and families facing life’s most difficult moments — through faith, community outreach, and compassionate care in Los Angeles County.
|
||||
</p>
|
||||
<div className="mt-8 flex flex-wrap items-center gap-3">
|
||||
<Magnetic>
|
||||
@@ -869,14 +877,14 @@ function Hero() {
|
||||
<a href="#/volunteers" className="btn-secondary">
|
||||
Volunteer <ArrowRight className="ml-1 h-4 w-4" />
|
||||
</a>
|
||||
<a href="#/stories" className="rounded-full border border-transparent px-4 py-2 text-sm text-neutral-700 underline-offset-4 hover:underline dark:text-neutral-300">
|
||||
Read stories
|
||||
<a href="#/about" className="rounded-full border border-transparent px-4 py-2 text-sm text-neutral-700 underline-offset-4 hover:underline dark:text-neutral-300">
|
||||
About us
|
||||
</a>
|
||||
</div>
|
||||
<ul className="mt-8 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-neutral-600 dark:text-neutral-400">
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-emerald-500"/> 501(c)(3) public charity</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-emerald-500"/> Donations tax-deductible</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-emerald-500"/> Community-driven impact</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-secondary-600"/> {SITE.legalStatus}</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-secondary-600"/> EIN {SITE.ein}</li>
|
||||
<li className="flex items-center gap-2"><CheckCircle2 className="h-4 w-4 text-secondary-600"/> Los Angeles County</li>
|
||||
</ul>
|
||||
</ParallaxContainer>
|
||||
</div>
|
||||
@@ -1028,10 +1036,10 @@ function HeroShowcase() {
|
||||
<div className="relative mx-auto max-w-sm lg:max-w-md xl:max-w-lg">
|
||||
<div className="absolute -inset-6 -z-10 rounded-3xl bg-gradient-to-tr from-primary-500/15 via-secondary-500/15 to-secondary-600/15 blur-2xl" />
|
||||
<div className="grid grid-cols-2 gap-3 sm:gap-4">
|
||||
<TiltCard icon={Backpack} title="School Supplies" desc="Backpacks, notebooks, calculators" />
|
||||
<TiltCard icon={Shirt} title="School Clothing" desc="Uniforms, shoes, coats" />
|
||||
<TiltCard icon={Sparkles} title="Everything Else" desc="Glasses, fees, emergencies" />
|
||||
<TiltCard icon={Users} title="Family Support" desc="Referrals & wraparound care" />
|
||||
<TiltCard icon={Users} title="Community Outreach" desc="Direct support for families in need" />
|
||||
<TiltCard icon={Heart} title="Crisis & Relief" desc="Fire, disaster, and emergency assistance" />
|
||||
<TiltCard icon={Shield} title="Advocacy & Navigation" desc="Resources, referrals, and compassionate care" />
|
||||
<TiltCard icon={Sparkles} title="Hope & Restoration" desc="Faith-rooted support when it matters most" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -1117,11 +1125,12 @@ function PartnerMarquee() {
|
||||
}
|
||||
|
||||
function Programs() {
|
||||
const items = [
|
||||
{ icon: Backpack, title: "School Supplies", body: "Backpacks, notebooks, art kits, calculators—ready for day one." },
|
||||
{ icon: Shirt, title: "School Clothing", body: "Uniforms, shoes, coats, and seasonal essentials in all sizes." },
|
||||
{ icon: Sparkles, title: "Everything Else", body: "Glasses, test fees, activity passes, hygiene kits—fast relief when needed." },
|
||||
]
|
||||
const icons = [Users, Heart, HomeIcon, Globe, Shield, Star] as const
|
||||
const items = WHAT_WE_DO.slice(0, 3).map((p, idx) => ({
|
||||
icon: icons[idx] ?? Heart,
|
||||
title: p.title,
|
||||
body: p.body,
|
||||
}))
|
||||
|
||||
return (
|
||||
<section id="programs" className="relative py-20 overflow-hidden">
|
||||
@@ -1149,7 +1158,7 @@ function Programs() {
|
||||
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<ParallaxContainer depth={0.2}>
|
||||
<SectionHeader eyebrow="What we do" title="Practical, student-first programs" subtitle="Flexible help that meets families where they are." />
|
||||
<SectionHeader eyebrow="What we do" title="Compassionate support when it matters most" subtitle="Outreach, advocacy, emergency assistance, and resource navigation for vulnerable populations." />
|
||||
</ParallaxContainer>
|
||||
<div className="mt-10 grid gap-6 md:grid-cols-3">
|
||||
{items.map((i, idx) => (
|
||||
@@ -1158,6 +1167,11 @@ function Programs() {
|
||||
</ParallaxContainer>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-10 text-center">
|
||||
<a href="#/what-we-do" className="btn-secondary">
|
||||
See all programs <ArrowRight className="ml-1 inline h-4 w-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
@@ -1216,11 +1230,11 @@ function FeatureCard({ icon: Icon, title, body }: FeatureCardProps) {
|
||||
}
|
||||
|
||||
function Impact() {
|
||||
const stats = [
|
||||
{ label: "Students equipped", value: 4200 },
|
||||
{ label: "Schools partnered", value: 38 },
|
||||
{ label: "Avg. response time (hrs)", value: 24 },
|
||||
{ label: "Counties served", value: 6 },
|
||||
const pillars = [
|
||||
{ label: "Community outreach", desc: "Direct support for underserved families" },
|
||||
{ label: "Emergency assistance", desc: "Crisis, fire, and disaster relief" },
|
||||
{ label: "Advocacy & navigation", desc: "Connecting people to hope and resources" },
|
||||
{ label: "Faith & restoration", desc: "Dignity, empathy, and compassionate care" },
|
||||
]
|
||||
|
||||
return (
|
||||
@@ -1251,41 +1265,38 @@ function Impact() {
|
||||
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 relative z-10">
|
||||
<ParallaxContainer depth={0.2}>
|
||||
<SectionHeader eyebrow="Impact" title="Every gift moves a student forward" subtitle="Transparent, measurable outcomes powered by local partnerships." />
|
||||
<SectionHeader eyebrow="Our heart" title="Healing begins when people feel seen" subtitle={SITE.closingLine} />
|
||||
</ParallaxContainer>
|
||||
|
||||
<div className="mt-12 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{stats.map((s, i) => (
|
||||
{pillars.map((s, i) => (
|
||||
<ParallaxContainer key={i} depth={0.3 + i * 0.05}>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 30, rotateX: -15 }}
|
||||
whileInView={{ opacity: 1, y: 0, rotateX: 0 }}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8, delay: i * 0.15 }}
|
||||
whileHover={{
|
||||
scale: 1.05,
|
||||
rotateY: 8,
|
||||
z: 60,
|
||||
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
|
||||
}}
|
||||
style={{ transformStyle: 'preserve-3d' }}
|
||||
className="card h-full text-center"
|
||||
>
|
||||
<Stat label={s.label} value={s.value} />
|
||||
<div className="font-semibold tracking-tight text-primary-800 dark:text-primary-100">{s.label}</div>
|
||||
<p className="mt-2 text-sm text-neutral-600 dark:text-neutral-400">{s.desc}</p>
|
||||
</motion.div>
|
||||
</ParallaxContainer>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-10 grid items-center gap-6 rounded-2xl border border-emerald-500/20 bg-emerald-500/10 p-6 sm:grid-cols-2">
|
||||
<div className="text-sm text-emerald-900 dark:text-emerald-100">
|
||||
<div className="font-medium">Where your donation goes</div>
|
||||
<ul className="mt-3 space-y-2">
|
||||
<li className="flex items-center gap-2"><span className="h-1.5 w-1.5 rounded-full bg-emerald-500"/> 85% programs • 10% ops • 5% fundraising</li>
|
||||
<li className="flex items-center gap-2"><span className="h-1.5 w-1.5 rounded-full bg-emerald-500"/> Average grant: $48 for supplies; $72 for clothing</li>
|
||||
</ul>
|
||||
<div className="mt-10 grid items-center gap-6 rounded-2xl border border-secondary-300/30 bg-secondary-50/50 p-6 sm:grid-cols-2 dark:border-secondary-700/30 dark:bg-secondary-900/20">
|
||||
<div className="text-sm text-primary-900 dark:text-primary-100">
|
||||
<div className="font-medium">Your gift restores hope</div>
|
||||
<p className="mt-3 leading-relaxed">
|
||||
Donations support outreach, emergency assistance, wellness support, and resource navigation for women, families, survivors, and communities in crisis throughout Los Angeles County.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-end">
|
||||
<a href="#/impact" className="btn-primary">
|
||||
See the impact report <ArrowRight className="ml-2 h-4 w-4" />
|
||||
<div className="flex flex-wrap items-center justify-end gap-3">
|
||||
<a href="#/donate" className="btn-primary">
|
||||
Donate <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</a>
|
||||
<a href="#/stories" className="btn-secondary">
|
||||
Stories of hope
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1294,32 +1305,6 @@ function Impact() {
|
||||
)
|
||||
}
|
||||
|
||||
function Stat({ label, value }: StatProps) {
|
||||
return (
|
||||
<div className="card text-center">
|
||||
<div className="absolute -right-10 -top-10 h-28 w-28 rounded-full bg-gradient-to-br from-primary-500/20 to-secondary-600/20 blur-2xl" />
|
||||
<div className="text-4xl font-semibold tracking-tight">
|
||||
<AnimatedNumber value={value} />
|
||||
</div>
|
||||
<div className="mt-2 text-sm text-neutral-600 dark:text-neutral-300">{label}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function AnimatedNumber({ value }: { value: number }) {
|
||||
const mv = useMotionValue(0)
|
||||
const spring = useSpring(mv, { stiffness: 90, damping: 15 })
|
||||
const rounded = useTransform(spring, (latest) => Math.floor(latest).toLocaleString())
|
||||
|
||||
useEffect(() => {
|
||||
mv.set(0)
|
||||
const timeout = setTimeout(() => mv.set(value), 150)
|
||||
return () => clearTimeout(timeout)
|
||||
}, [value, mv])
|
||||
|
||||
return <motion.span>{rounded}</motion.span>
|
||||
}
|
||||
|
||||
function HowItWorks() {
|
||||
const steps = [
|
||||
{ title: "Referral", body: "A school counselor, social worker, or parent submits a simple request." },
|
||||
@@ -1583,10 +1568,10 @@ function CTA() {
|
||||
<h3 className="font-medium tracking-tight">Prefer offline?</h3>
|
||||
<ul className="mt-3 space-y-2 text-sm text-white/90">
|
||||
<li className="flex items-center gap-2"><MapPin className="h-4 w-4"/> 20274 Via Medici, Porter Ranch, CA 91326</li>
|
||||
<li className="flex items-center gap-2"><Mail className="h-4 w-4"/> [email protected]</li>
|
||||
<li className="flex items-center gap-2"><Mail className="h-4 w-4"/> {SITE.email}</li>
|
||||
<li className="flex items-center gap-2"><Phone className="h-4 w-4"/> (818) 491-6884</li>
|
||||
</ul>
|
||||
<p className="mt-3 text-xs text-white/80">Miracles in Motion is a 501(c)(3). EIN 88-1234567.</p>
|
||||
<p className="mt-3 text-xs text-white/80">{SITE.legalStatus}. EIN {SITE.ein}.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1995,7 +1980,7 @@ function DonatePage() {
|
||||
<span>Secure 256-bit SSL encryption</span>
|
||||
</div>
|
||||
<p className="text-xs text-neutral-500 dark:text-neutral-500 mt-2">
|
||||
You'll receive an email receipt for your tax records. Donations are tax-deductible to the extent allowed by law. EIN 12-3456789.
|
||||
You'll receive an email receipt for your tax records. Donations are tax-deductible to the extent allowed by law. EIN {SITE.ein}.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2012,7 +1997,7 @@ function DonatePage() {
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-neutral-700 dark:text-neutral-300 mb-3">
|
||||
Many employers will match your charitable donation. Check with your HR department and provide our EIN: 12-3456789.
|
||||
Many employers will match your charitable donation. Check with your HR department and provide our EIN: {SITE.ein}.
|
||||
</p>
|
||||
<a href="#" className="inline-flex items-center gap-2 text-sm text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded">
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
@@ -2115,8 +2100,8 @@ function DonatePage() {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Mail className="h-4 w-4 text-primary-600 dark:text-primary-400" />
|
||||
<a href="mailto:[email protected]" className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300">
|
||||
contact@mim4u.org
|
||||
<a href={SITE.emailHref} className="text-primary-600 dark:text-primary-400 hover:text-primary-700 dark:hover:text-primary-300">
|
||||
{SITE.email}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2230,13 +2215,14 @@ function SponsorsPage() {
|
||||
|
||||
function StoriesPage() {
|
||||
const stories = [
|
||||
{ title: "Ready on Day One", tag: "Supplies", body: "A 3rd grader received a backpack and art kit, returning to class with pride.", by: "Ms. Lee, Teacher" },
|
||||
{ title: "Warm for Winter", tag: "Clothing", body: "A high schooler got a coat and shoes before a cold snap—attendance rebounded.", by: "School Social Worker" },
|
||||
{ title: "Glasses for Growth", tag: "Everything Else", body: "A student's new glasses improved reading in two weeks.", by: "Counselor" },
|
||||
{ title: "A family found hope again", tag: "Outreach", body: "After a fire displaced their home, a mother and children received emergency support and compassionate guidance through recovery.", by: "Community partner" },
|
||||
{ title: "Strength after hardship", tag: "Advocacy", body: "A survivor connected with resources and encouragement — reminded that she matters and brighter days are ahead.", by: "Volunteer" },
|
||||
{ title: "Community showed up", tag: "Events", body: "Neighbors and volunteers came together at an outreach event to serve families with supplies, prayer, and heartfelt support.", by: "Event volunteer" },
|
||||
]
|
||||
|
||||
return (
|
||||
<PageShell title="Stories" icon={BookOpenText} eyebrow="Impact in motion" cta={<a href="#/testimonies" className="btn-secondary">Read testimonies</a>}>
|
||||
<PageShell title="Stories of Hope" icon={BookOpenText} eyebrow="Hope in motion" cta={<a href="#/testimonies" className="btn-secondary">Read testimonies</a>}>
|
||||
<StoriesIntroBlock />
|
||||
<div className="grid gap-6 md:grid-cols-3">
|
||||
{stories.map((s, i) => (
|
||||
<article key={i} className="card">
|
||||
@@ -2289,7 +2275,7 @@ function ImpactReportPage() {
|
||||
<PageShell title="Impact Report" icon={BarChart3} eyebrow="Our impact in numbers" cta={<a href="#/donate" className="btn-primary">Donate to support more students</a>}>
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
<p className="text-lg text-neutral-700 dark:text-neutral-300">
|
||||
Miracles in Motion provides essential supplies, clothing, and support to students in need. Below is a summary of our impact. For the full report or data requests, contact <a className="underline" href="mailto:[email protected]">contact@mim4u.org</a>.
|
||||
Miracles in Motion Foundation serves vulnerable individuals and families across Los Angeles County. For impact updates or data requests, contact <a className="underline" href={SITE.emailHref}>{SITE.email}</a>.
|
||||
</p>
|
||||
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<div className="card text-center">
|
||||
@@ -2365,7 +2351,7 @@ function LegalPage() {
|
||||
<p>We aim to meet WCAG 2.1 AA standards. If you encounter accessibility barriers, email <a className="underline" href="mailto:[email protected]">access@miraclesinmotion.org</a>.</p>
|
||||
</PolicySection>
|
||||
<PolicySection id="financials" title="Financials & 990">
|
||||
<p>Miracles in Motion is a 501(c)(3) nonprofit. EIN 12-3456789. Annual reports and Form 990s are available upon request or linked here when published.</p>
|
||||
<p>{SITE.name} is a {SITE.legalStatus.toLowerCase()}. EIN {SITE.ein}. Annual reports and Form 990s are available upon request or linked here when published.</p>
|
||||
</PolicySection>
|
||||
<PolicySection id="sponsorship-terms" title="Sponsorship Terms & Logo Use">
|
||||
<ul className="list-disc pl-5 space-y-2">
|
||||
@@ -4558,7 +4544,7 @@ function AppContent() {
|
||||
// Update document title based on current route
|
||||
useEffect(() => {
|
||||
document.title = currentPath === "/"
|
||||
? "Miracles in Motion — Essentials for Every Student"
|
||||
? `${SITE.name} — ${SITE.brandMessage}`
|
||||
: `Miracles in Motion — ${currentPath.replace("/", "").replace(/-/g, " ").replace(/\b\w/g, (m) => m.toUpperCase())}`
|
||||
}, [currentPath])
|
||||
|
||||
@@ -4579,6 +4565,16 @@ function AppContent() {
|
||||
return <LegalPage />
|
||||
case '/brand':
|
||||
return <BrandAssetsPage />
|
||||
case '/about':
|
||||
return <AboutPage />
|
||||
case '/mission':
|
||||
return <MissionPage />
|
||||
case '/what-we-do':
|
||||
return <WhatWeDoPage />
|
||||
case '/events':
|
||||
return <EventsPage />
|
||||
case '/contact':
|
||||
return <ContactPage />
|
||||
case '/impact':
|
||||
return <ImpactReportPage />
|
||||
case '/request-assistance':
|
||||
|
||||
+84
-26
@@ -1,62 +1,120 @@
|
||||
import {
|
||||
Facebook,
|
||||
Globe,
|
||||
Instagram,
|
||||
} from 'lucide-react'
|
||||
import { Facebook, Globe, Instagram, Mail } from 'lucide-react'
|
||||
import { SITE } from '../content/siteContent'
|
||||
import { LogoMark } from './ui/LogoMark'
|
||||
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer className="relative mt-24 border-t border-white/30 bg-white/50 backdrop-blur dark:border-white/10 dark:bg-white/5">
|
||||
<footer className="relative mt-24 border-t border-secondary-200/60 bg-[var(--mim-cream)]/90 backdrop-blur dark:border-white/10 dark:bg-white/5">
|
||||
<div className="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
|
||||
<div className="grid gap-8 lg:grid-cols-4">
|
||||
<div className="lg:col-span-2">
|
||||
<div className="footer-brand-block">
|
||||
<LogoMark variant="footer" />
|
||||
<p className="footer-tagline">Essentials for every student</p>
|
||||
<p className="footer-tagline">{SITE.tagline}</p>
|
||||
</div>
|
||||
<p className="mt-4 max-w-md text-sm text-neutral-600 dark:text-neutral-400">
|
||||
A 501(c)(3) nonprofit providing students with school supplies, clothing, and emergency support to help them succeed.
|
||||
<p className="mt-4 max-w-md text-sm leading-relaxed text-neutral-700 dark:text-neutral-300">
|
||||
{SITE.brandMessage}
|
||||
</p>
|
||||
<p className="mt-3 text-sm text-neutral-600 dark:text-neutral-400">{SITE.serviceArea}</p>
|
||||
<div className="mt-4 flex gap-4">
|
||||
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400">
|
||||
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400" aria-label="Facebook">
|
||||
<Facebook className="h-5 w-5" />
|
||||
</a>
|
||||
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400">
|
||||
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400" aria-label="Instagram">
|
||||
<Instagram className="h-5 w-5" />
|
||||
</a>
|
||||
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400">
|
||||
<a href="#" className="text-neutral-600 hover:text-primary-600 dark:text-neutral-400" aria-label="Website">
|
||||
<Globe className="h-5 w-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-semibold">Get Involved</h3>
|
||||
<ul className="mt-4 space-y-2 text-sm">
|
||||
<li><a href="#/donate" className="navlink">Donate</a></li>
|
||||
<li><a href="#/volunteers" className="navlink">Volunteer</a></li>
|
||||
<li><a href="#/sponsors" className="navlink">Corporate Partnerships</a></li>
|
||||
<li><a href="#/stories" className="navlink">Success Stories</a></li>
|
||||
<li>
|
||||
<a href="#/donate" className="navlink">
|
||||
Donate
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/volunteers" className="navlink">
|
||||
Volunteer
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/events" className="navlink">
|
||||
Community Events
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/stories" className="navlink">
|
||||
Stories of Hope
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="font-semibold">Organization</h3>
|
||||
<h3 className="font-semibold">About</h3>
|
||||
<ul className="mt-4 space-y-2 text-sm">
|
||||
<li><a href="#/testimonies" className="navlink">Testimonials</a></li>
|
||||
<li><a href="#/brand" className="navlink">Brand assets</a></li>
|
||||
<li><a href="#/legal" className="navlink">Legal & Policies</a></li>
|
||||
<li><a href="mailto:[email protected]" className="navlink">Contact Us</a></li>
|
||||
<li><a href="tel:+18184916884" className="navlink">(818) 491-6884</a></li>
|
||||
<li>
|
||||
<a href="#/about" className="navlink">
|
||||
About Us
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/mission" className="navlink">
|
||||
Our Mission
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/what-we-do" className="navlink">
|
||||
What We Do
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/contact" className="navlink">
|
||||
Contact Us
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href={SITE.emailHref} className="navlink inline-flex items-center gap-1">
|
||||
<Mail className="h-3.5 w-3.5" aria-hidden />
|
||||
{SITE.email}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/request-assistance" className="navlink">
|
||||
Request assistance
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#/legal" className="navlink">
|
||||
Legal & Policies
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 border-t border-white/30 pt-8 text-center text-xs text-neutral-500 dark:border-white/10 dark:text-neutral-400">
|
||||
<p>© 2025 Miracles in Motion. All rights reserved. EIN: 88-1234567</p>
|
||||
<p className="mt-1">501(c)(3) nonprofit organization. Donations are tax-deductible to the extent allowed by law.</p>
|
||||
|
||||
<div className="mt-8 border-t border-secondary-200/50 pt-8 text-center text-xs text-neutral-600 dark:border-white/10 dark:text-neutral-400">
|
||||
<p className="font-medium text-neutral-800 dark:text-neutral-200">{SITE.name}</p>
|
||||
<p className="mt-1">{SITE.legalStatus}</p>
|
||||
<p className="mt-1">
|
||||
EIN:{' '}
|
||||
<a href={`tel:${SITE.ein.replace(/-/g, '')}`} className="underline">
|
||||
{SITE.ein}
|
||||
</a>
|
||||
</p>
|
||||
<p className="mt-2">
|
||||
© {new Date().getFullYear()} {SITE.shortName}. All rights reserved. Donations may be
|
||||
tax-deductible to the extent allowed by law.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
export default Footer
|
||||
export default Footer
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { motion } from 'framer-motion'
|
||||
import {
|
||||
Heart,
|
||||
Menu,
|
||||
Moon,
|
||||
SunMedium,
|
||||
X,
|
||||
} from 'lucide-react'
|
||||
import { Heart, Menu, Moon, SunMedium, X } from 'lucide-react'
|
||||
import { NAV_LINKS } from '../content/siteContent'
|
||||
import { trackEvent } from '../utils/analytics'
|
||||
|
||||
// Import UI components
|
||||
import { Magnetic, LogoMark } from './ui'
|
||||
|
||||
interface NavProps {
|
||||
@@ -20,12 +13,10 @@ interface NavProps {
|
||||
}
|
||||
|
||||
export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMenuOpen }: NavProps) {
|
||||
// Close mobile menu when route changes
|
||||
useEffect(() => {
|
||||
setMobileMenuOpen(false)
|
||||
}, [window.location.hash])
|
||||
}, [window.location.hash, setMobileMenuOpen])
|
||||
|
||||
// Handle keyboard navigation
|
||||
const handleKeyDown = (e: React.KeyboardEvent, action: () => void) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault()
|
||||
@@ -33,39 +24,51 @@ export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMen
|
||||
}
|
||||
}
|
||||
|
||||
const navLinkClass =
|
||||
'navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded text-sm lg:text-[0.9375rem]'
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className="mim-site-nav mx-auto flex w-full max-w-7xl items-center justify-between px-4 py-3 sm:px-6 lg:px-8 lg:py-4" role="navigation" aria-label="Main navigation">
|
||||
<div className="flex items-center gap-3">
|
||||
<a
|
||||
href="#/"
|
||||
className="nav-brand-link focus:outline-none"
|
||||
aria-label="Miracles in Motion Foundation — Home"
|
||||
>
|
||||
<LogoMark variant="nav" />
|
||||
<span className="sr-only">Essentials for every student</span>
|
||||
</a>
|
||||
<nav
|
||||
className="mim-site-nav mx-auto flex w-full max-w-7xl items-center justify-between gap-2 px-4 py-3 sm:px-6 lg:px-8 lg:py-4"
|
||||
role="navigation"
|
||||
aria-label="Main navigation"
|
||||
>
|
||||
<a
|
||||
href="#/"
|
||||
className="nav-brand-link shrink-0 focus:outline-none"
|
||||
aria-label="Miracles in Motion Foundation — Home"
|
||||
>
|
||||
<LogoMark variant="nav" />
|
||||
</a>
|
||||
|
||||
<div className="hidden items-center gap-4 xl:gap-5 lg:flex">
|
||||
{NAV_LINKS.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
className={navLinkClass}
|
||||
href={link.href}
|
||||
aria-label={link.ariaLabel}
|
||||
onClick={
|
||||
link.href === '#/volunteers'
|
||||
? () => trackEvent('cta_clicked', { button: 'volunteer', location: 'nav' })
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden items-center gap-6 md:flex">
|
||||
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/stories" aria-label="Read success stories">Stories</a>
|
||||
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/testimonies" aria-label="View testimonies">Testimonies</a>
|
||||
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/volunteers" aria-label="Volunteer opportunities" onClick={() => trackEvent('cta_clicked', { button: 'volunteer', location: 'nav' })}>Volunteers</a>
|
||||
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/sponsors" aria-label="Corporate partnerships">Corporate</a>
|
||||
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/request-assistance" aria-label="Request assistance">Get Help</a>
|
||||
<a className="navlink focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded" href="#/portals" aria-label="Portal login">Portals</a>
|
||||
</div>
|
||||
|
||||
{/* Desktop Actions */}
|
||||
<div className="hidden md:flex items-center gap-3">
|
||||
|
||||
<div className="hidden items-center gap-3 lg:flex">
|
||||
<Magnetic>
|
||||
<a
|
||||
href="#/donate"
|
||||
className="btn-primary focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
|
||||
aria-label="Make a donation"
|
||||
>
|
||||
<Heart className="mr-2 h-4 w-4" aria-hidden="true" /> Donate
|
||||
<Heart className="mr-2 h-4 w-4" aria-hidden />
|
||||
Donate
|
||||
</a>
|
||||
</Magnetic>
|
||||
<button
|
||||
@@ -75,73 +78,73 @@ export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMen
|
||||
className="group rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 hover:bg-white dark:border-white/10 dark:bg-white/10 dark:hover:bg-white/15 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
|
||||
>
|
||||
{darkMode ? (
|
||||
<SunMedium className="h-5 w-5 transition group-hover:rotate-12" aria-hidden="true" />
|
||||
<SunMedium className="h-5 w-5 transition group-hover:rotate-12" aria-hidden />
|
||||
) : (
|
||||
<Moon className="h-5 w-5 transition group-hover:-rotate-12" aria-hidden="true" />
|
||||
<Moon className="h-5 w-5 transition group-hover:-rotate-12" aria-hidden />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Actions */}
|
||||
<div className="flex md:hidden items-center gap-2">
|
||||
|
||||
<div className="flex items-center gap-2 lg:hidden">
|
||||
<Magnetic>
|
||||
<a
|
||||
href="#/donate"
|
||||
className="btn-primary text-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
|
||||
className="btn-primary px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500"
|
||||
aria-label="Make a donation"
|
||||
>
|
||||
<Heart className="h-4 w-4" aria-hidden="true" />
|
||||
<Heart className="h-4 w-4" aria-hidden />
|
||||
</a>
|
||||
</Magnetic>
|
||||
<button
|
||||
aria-label={darkMode ? 'Switch to light mode' : 'Switch to dark mode'}
|
||||
onClick={() => setDarkMode(!darkMode)}
|
||||
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 hover:bg-white dark:border-white/10 dark:bg-white/10 dark:hover:bg-white/15 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
|
||||
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 dark:border-white/10 dark:bg-white/10"
|
||||
>
|
||||
{darkMode ? (
|
||||
<SunMedium className="h-4 w-4" aria-hidden="true" />
|
||||
) : (
|
||||
<Moon className="h-4 w-4" aria-hidden="true" />
|
||||
)}
|
||||
{darkMode ? <SunMedium className="h-4 w-4" aria-hidden /> : <Moon className="h-4 w-4" aria-hidden />}
|
||||
</button>
|
||||
<button
|
||||
aria-label={mobileMenuOpen ? 'Close navigation menu' : 'Open navigation menu'}
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
onKeyDown={(e) => handleKeyDown(e, () => setMobileMenuOpen(!mobileMenuOpen))}
|
||||
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm transition hover:scale-105 hover:bg-white dark:border-white/10 dark:bg-white/10 dark:hover:bg-white/15 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
|
||||
className="rounded-full border border-neutral-200/70 bg-white/70 p-2 shadow-sm dark:border-white/10 dark:bg-white/10"
|
||||
aria-expanded={mobileMenuOpen}
|
||||
aria-controls="mobile-menu"
|
||||
>
|
||||
{mobileMenuOpen ? (
|
||||
<X className="h-5 w-5" aria-hidden="true" />
|
||||
) : (
|
||||
<Menu className="h-5 w-5" aria-hidden="true" />
|
||||
)}
|
||||
{mobileMenuOpen ? <X className="h-5 w-5" aria-hidden /> : <Menu className="h-5 w-5" aria-hidden />}
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
|
||||
<motion.div
|
||||
id="mobile-menu"
|
||||
className="md:hidden"
|
||||
className="lg:hidden"
|
||||
initial={false}
|
||||
animate={{
|
||||
height: mobileMenuOpen ? 'auto' : 0,
|
||||
opacity: mobileMenuOpen ? 1 : 0
|
||||
}}
|
||||
exit={{ height: 0, opacity: 0 }}
|
||||
animate={{ height: mobileMenuOpen ? 'auto' : 0, opacity: mobileMenuOpen ? 1 : 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
style={{ overflow: 'hidden' }}
|
||||
>
|
||||
<div className="border-t border-neutral-200/50 bg-white/95 px-4 py-3 backdrop-blur dark:border-white/10 dark:bg-black/90">
|
||||
<div className="space-y-3">
|
||||
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/stories">Stories</a>
|
||||
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/testimonies">Testimonies</a>
|
||||
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/volunteers" onClick={() => trackEvent('cta_clicked', { button: 'volunteer', location: 'nav_mobile' })}>Volunteers</a>
|
||||
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/sponsors">Corporate</a>
|
||||
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/request-assistance">Get Help</a>
|
||||
<a className="block py-2 text-sm font-medium rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2" href="#/portals">Portals</a>
|
||||
<div className="border-t border-secondary-200/50 bg-[var(--mim-cream)]/95 px-4 py-3 backdrop-blur dark:border-white/10 dark:bg-black/90">
|
||||
<div className="space-y-1">
|
||||
<a className="block rounded py-2 text-sm font-medium" href="#/">
|
||||
Home
|
||||
</a>
|
||||
{NAV_LINKS.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
className="block rounded py-2 text-sm font-medium focus-visible:ring-2 focus-visible:ring-primary-500"
|
||||
href={link.href}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
<a className="block rounded py-2 text-sm font-medium" href="#/donate">
|
||||
Donate
|
||||
</a>
|
||||
<a
|
||||
className="block rounded py-2 text-sm text-neutral-600 dark:text-neutral-400"
|
||||
href="#/request-assistance"
|
||||
>
|
||||
Request assistance
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
@@ -149,4 +152,4 @@ export function Navigation({ darkMode, setDarkMode, mobileMenuOpen, setMobileMen
|
||||
)
|
||||
}
|
||||
|
||||
export default Navigation
|
||||
export default Navigation
|
||||
|
||||
@@ -15,8 +15,9 @@ interface SEOHeadProps {
|
||||
}
|
||||
|
||||
export function SEOHead({
|
||||
title = 'Miracles in Motion - Empowering Students with Essential Support',
|
||||
description = 'A 501(c)(3) nonprofit providing students with school supplies, clothing, and emergency support to help them succeed in school and life.',
|
||||
title = 'Miracles in Motion Foundation — Restoring hope through compassion, community, and faith',
|
||||
description =
|
||||
'A California nonprofit bringing hope, compassion, and support to individuals and families in crisis throughout Los Angeles County — community outreach, emergency assistance, advocacy, and faith-rooted care.',
|
||||
image = '/og-image.png',
|
||||
url = 'https://mim4u.org',
|
||||
type = 'website',
|
||||
@@ -100,7 +101,7 @@ export function SEOHead({
|
||||
"@type": "ContactPoint",
|
||||
"telephone": "+1-818-491-6884",
|
||||
"contactType": "customer service",
|
||||
"email": "contact@mim4u.org"
|
||||
"email": "info@faithforwardmiracles.org"
|
||||
},
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
|
||||
@@ -3,72 +3,57 @@ import { render } from '@testing-library/react'
|
||||
import { screen } from '@testing-library/dom'
|
||||
import '@testing-library/jest-dom'
|
||||
import { Footer } from '../Footer'
|
||||
import { SITE } from '../../content/siteContent'
|
||||
|
||||
// Mock the LogoMark component
|
||||
vi.mock('../ui/LogoMark', () => ({
|
||||
LogoMark: () => <div data-testid="logo-mark">Logo</div>
|
||||
LogoMark: () => <div data-testid="logo-mark">Logo</div>,
|
||||
}))
|
||||
|
||||
describe('Footer Component', () => {
|
||||
it('renders footer with logo and brand information', () => {
|
||||
render(<Footer />)
|
||||
|
||||
|
||||
expect(screen.getByTestId('logo-mark')).toBeInTheDocument()
|
||||
expect(screen.getByText('Miracles in Motion')).toBeInTheDocument()
|
||||
expect(screen.getByText('Essentials for every student')).toBeInTheDocument()
|
||||
expect(screen.getByText(SITE.tagline)).toBeInTheDocument()
|
||||
expect(screen.getByText(SITE.brandMessage)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders organization description', () => {
|
||||
it('renders service area', () => {
|
||||
render(<Footer />)
|
||||
|
||||
expect(screen.getByText(/A 501\(c\)\(3\) nonprofit providing students/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders social media links', () => {
|
||||
render(<Footer />)
|
||||
|
||||
const socialLinks = screen.getAllByRole('link')
|
||||
const socialIcons = socialLinks.filter((link: HTMLElement) =>
|
||||
link.getAttribute('href') === '#'
|
||||
)
|
||||
|
||||
expect(socialIcons).toHaveLength(3) // Facebook, Instagram, Globe
|
||||
expect(screen.getByText(/Los Angeles County/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders Get Involved section with correct links', () => {
|
||||
render(<Footer />)
|
||||
|
||||
|
||||
expect(screen.getByText('Get Involved')).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Donate' })).toHaveAttribute('href', '#/donate')
|
||||
expect(screen.getByRole('link', { name: 'Volunteer' })).toHaveAttribute('href', '#/volunteers')
|
||||
expect(screen.getByRole('link', { name: 'Corporate Partnerships' })).toHaveAttribute('href', '#/sponsors')
|
||||
expect(screen.getByRole('link', { name: 'Success Stories' })).toHaveAttribute('href', '#/stories')
|
||||
expect(screen.getByRole('link', { name: 'Community Events' })).toHaveAttribute('href', '#/events')
|
||||
expect(screen.getByRole('link', { name: 'Stories of Hope' })).toHaveAttribute('href', '#/stories')
|
||||
})
|
||||
|
||||
it('renders Organization section with correct links', () => {
|
||||
it('renders About section with contact email', () => {
|
||||
render(<Footer />)
|
||||
|
||||
expect(screen.getByText('Organization')).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: 'Testimonials' })).toHaveAttribute('href', '#/testimonies')
|
||||
expect(screen.getByRole('link', { name: 'Legal & Policies' })).toHaveAttribute('href', '#/legal')
|
||||
expect(screen.getByRole('link', { name: 'Contact Us' })).toHaveAttribute('href', 'mailto:[email protected]')
|
||||
expect(screen.getByRole('link', { name: '(818) 491-6884' })).toHaveAttribute('href', 'tel:+18184916884')
|
||||
|
||||
expect(screen.getByText('About')).toBeInTheDocument()
|
||||
expect(screen.getByRole('link', { name: SITE.email })).toHaveAttribute('href', SITE.emailHref)
|
||||
expect(screen.getByRole('link', { name: 'About Us' })).toHaveAttribute('href', '#/about')
|
||||
expect(screen.getByRole('link', { name: 'Our Mission' })).toHaveAttribute('href', '#/mission')
|
||||
})
|
||||
|
||||
it('renders copyright information', () => {
|
||||
it('renders legal and EIN', () => {
|
||||
render(<Footer />)
|
||||
|
||||
expect(screen.getByText(/© 2025 Miracles in Motion. All rights reserved./)).toBeInTheDocument()
|
||||
expect(screen.getByText(/501\(c\)\(3\) nonprofit organization./)).toBeInTheDocument()
|
||||
|
||||
expect(screen.getByText(SITE.name)).toBeInTheDocument()
|
||||
expect(screen.getByText(SITE.legalStatus)).toBeInTheDocument()
|
||||
expect(screen.getByText(new RegExp(SITE.ein))).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('has proper accessibility structure', () => {
|
||||
render(<Footer />)
|
||||
|
||||
const footer = screen.getByRole('contentinfo')
|
||||
expect(footer).toBeInTheDocument()
|
||||
|
||||
const headings = screen.getAllByRole('heading', { level: 3 })
|
||||
expect(headings).toHaveLength(2) // "Get Involved" and "Organization"
|
||||
|
||||
expect(screen.getByRole('contentinfo')).toBeInTheDocument()
|
||||
expect(screen.getAllByRole('heading', { level: 3 })).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,10 +4,9 @@ import { screen, fireEvent } from '@testing-library/dom'
|
||||
import '@testing-library/jest-dom'
|
||||
import { Navigation } from '../Navigation'
|
||||
|
||||
// Mock the UI components
|
||||
vi.mock('../ui', () => ({
|
||||
LogoMark: () => <div data-testid="logo-mark">Logo</div>,
|
||||
Magnetic: ({ children }: { children: React.ReactNode }) => <div>{children}</div>
|
||||
Magnetic: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
|
||||
}))
|
||||
|
||||
describe('Navigation Component', () => {
|
||||
@@ -15,7 +14,7 @@ describe('Navigation Component', () => {
|
||||
darkMode: false,
|
||||
setDarkMode: vi.fn(),
|
||||
mobileMenuOpen: false,
|
||||
setMobileMenuOpen: vi.fn()
|
||||
setMobileMenuOpen: vi.fn(),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -26,64 +25,39 @@ describe('Navigation Component', () => {
|
||||
render(<Navigation {...mockProps} />)
|
||||
|
||||
expect(screen.getByTestId('logo-mark')).toBeInTheDocument()
|
||||
expect(
|
||||
screen.getByLabelText('Miracles in Motion Foundation — Home')
|
||||
).toBeInTheDocument()
|
||||
expect(screen.getByText('Essentials for every student')).toHaveClass('sr-only')
|
||||
expect(screen.getByLabelText('Miracles in Motion Foundation — Home')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders desktop navigation links', () => {
|
||||
it('renders primary navigation links', () => {
|
||||
render(<Navigation {...mockProps} />)
|
||||
|
||||
expect(screen.getByLabelText('Read success stories')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('View testimonies')).toBeInTheDocument()
|
||||
|
||||
expect(screen.getByLabelText('About us')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Our programs and services')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Stories of hope')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Community events')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Volunteer opportunities')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Corporate partnerships')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Request assistance')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Portal login')).toBeInTheDocument()
|
||||
expect(screen.getByLabelText('Contact us')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('toggles dark mode when button is clicked', () => {
|
||||
render(<Navigation {...mockProps} />)
|
||||
|
||||
const darkModeButtons = screen.getAllByLabelText('Switch to dark mode')
|
||||
fireEvent.click(darkModeButtons[0])
|
||||
|
||||
|
||||
fireEvent.click(screen.getAllByLabelText('Switch to dark mode')[0])
|
||||
expect(mockProps.setDarkMode).toHaveBeenCalledWith(true)
|
||||
})
|
||||
|
||||
it('toggles mobile menu when hamburger button is clicked', () => {
|
||||
render(<Navigation {...mockProps} />)
|
||||
|
||||
const mobileMenuButton = screen.getByLabelText('Open navigation menu')
|
||||
fireEvent.click(mobileMenuButton)
|
||||
|
||||
|
||||
fireEvent.click(screen.getByLabelText('Open navigation menu'))
|
||||
expect(mockProps.setMobileMenuOpen).toHaveBeenCalledWith(true)
|
||||
})
|
||||
|
||||
it('displays mobile menu when mobileMenuOpen is true', () => {
|
||||
render(<Navigation {...mockProps} mobileMenuOpen={true} />)
|
||||
|
||||
const storiesLinks = screen.getAllByText('Stories')
|
||||
expect(storiesLinks).toHaveLength(2) // One in desktop nav, one in mobile nav
|
||||
expect(screen.getByText('Testimonies')).toBeInTheDocument()
|
||||
expect(screen.getByText('Volunteers')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('handles keyboard navigation correctly', () => {
|
||||
render(<Navigation {...mockProps} />)
|
||||
|
||||
const darkModeButton = screen.getAllByLabelText('Switch to dark mode')[0]
|
||||
fireEvent.keyDown(darkModeButton, { key: 'Enter', code: 'Enter' })
|
||||
|
||||
expect(mockProps.setDarkMode).toHaveBeenCalledWith(true)
|
||||
expect(screen.getAllByText('Stories').length).toBeGreaterThanOrEqual(1)
|
||||
expect(screen.getByText('Events')).toBeInTheDocument()
|
||||
expect(screen.getByText('Contact')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('displays correct icon based on dark mode state', () => {
|
||||
const { rerender } = render(<Navigation {...mockProps} darkMode={false} />)
|
||||
expect(screen.getAllByLabelText('Switch to dark mode')).toHaveLength(2)
|
||||
|
||||
rerender(<Navigation {...mockProps} darkMode={true} />)
|
||||
expect(screen.getAllByLabelText('Switch to light mode')).toHaveLength(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Heart } from 'lucide-react'
|
||||
import { INTRO, POPULATIONS_SERVED, SITE } from '../../content/siteContent'
|
||||
|
||||
export function WhoWeServe() {
|
||||
return (
|
||||
<section className="relative py-20 mim-warm-section">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="section-header mx-auto max-w-3xl text-center">
|
||||
<div className="section-eyebrow">{SITE.tagline}</div>
|
||||
<h2 className="section-title">Hope for those who need it most</h2>
|
||||
<p className="section-subtitle">{INTRO.lead}</p>
|
||||
</div>
|
||||
|
||||
<p className="mx-auto mt-6 max-w-3xl text-center text-neutral-700 dark:text-neutral-300">
|
||||
{INTRO.belief}
|
||||
</p>
|
||||
|
||||
<div className="mt-12 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{POPULATIONS_SERVED.map((item) => (
|
||||
<div
|
||||
key={item}
|
||||
className="flex items-start gap-3 rounded-2xl border border-secondary-200/50 bg-white/80 p-4 shadow-sm dark:border-white/10 dark:bg-white/5"
|
||||
>
|
||||
<Heart
|
||||
className="mt-0.5 h-5 w-5 shrink-0 text-secondary-500"
|
||||
aria-hidden
|
||||
/>
|
||||
<span className="text-sm leading-relaxed text-neutral-800 dark:text-neutral-200">
|
||||
{item}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<p className="mx-auto mt-10 max-w-2xl text-center text-sm text-neutral-600 dark:text-neutral-400">
|
||||
{INTRO.scope}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/** Client-approved copy and contact — single source of truth for the public site. */
|
||||
export const SITE = {
|
||||
name: 'Miracles in Motion Foundation',
|
||||
shortName: 'Miracles in Motion',
|
||||
tagline: 'Faith • Hope • Community • Restoration',
|
||||
brandMessage: 'Restoring hope through compassion, community, and faith.',
|
||||
email: '[email protected]',
|
||||
emailHref: 'mailto:[email protected]',
|
||||
ein: '33-4887159',
|
||||
legalStatus: 'California Nonprofit Public Benefit Corporation',
|
||||
serviceArea:
|
||||
'Serving Los Angeles County with a vision to expand throughout California and beyond.',
|
||||
closingLine: 'Because miracles still happen every day.',
|
||||
} as const
|
||||
|
||||
export const NAV_LINKS = [
|
||||
{ href: '#/about', label: 'About', ariaLabel: 'About us' },
|
||||
{ href: '#/what-we-do', label: 'What We Do', ariaLabel: 'Our programs and services' },
|
||||
{ href: '#/stories', label: 'Stories', ariaLabel: 'Stories of hope' },
|
||||
{ href: '#/events', label: 'Events', ariaLabel: 'Community events' },
|
||||
{ href: '#/volunteers', label: 'Volunteer', ariaLabel: 'Volunteer opportunities' },
|
||||
{ href: '#/contact', label: 'Contact', ariaLabel: 'Contact us' },
|
||||
] as const
|
||||
|
||||
export const INTRO = {
|
||||
lead:
|
||||
'Miracles in Motion Foundation was created to bring hope, compassion, and support to individuals and families facing life’s most difficult moments.',
|
||||
body:
|
||||
'Founded through lived experience, resilience, and faith, our mission is rooted in helping those who feel unheard, overlooked, or alone during times of crisis and hardship.',
|
||||
belief:
|
||||
'At Miracles in Motion Foundation, we believe healing begins when people feel seen, valued, and supported.',
|
||||
scope:
|
||||
'Our organization focuses on community outreach, emergency assistance, wellness support, advocacy, resource navigation, and compassionate care for vulnerable populations throughout Los Angeles County — with a vision of expanding our impact across California and beyond.',
|
||||
restoration:
|
||||
'We believe that even during the hardest seasons of life, restoration is possible.',
|
||||
} as const
|
||||
|
||||
export const POPULATIONS_SERVED = [
|
||||
'Women and single mothers',
|
||||
'Teen mothers and youth',
|
||||
'Families in crisis',
|
||||
'Survivors of domestic violence',
|
||||
'Individuals experiencing homelessness',
|
||||
'Families affected by disasters and fire emergencies',
|
||||
'Underserved communities needing hope, guidance, and support',
|
||||
] as const
|
||||
|
||||
export const MISSION = {
|
||||
statement:
|
||||
'Our mission is to restore hope, provide compassionate support, and empower individuals and families facing crisis, hardship, trauma, and instability through community outreach, advocacy, emergency assistance, and life-changing resources.',
|
||||
dedication:
|
||||
'We are dedicated to serving vulnerable populations with dignity, empathy, and faith while helping create pathways toward healing, stability, and restoration.',
|
||||
} as const
|
||||
|
||||
export const WHY_WE_STARTED = {
|
||||
lead:
|
||||
'Miracles in Motion Foundation was born from real-life experiences with hardship, survival, rebuilding, and faith.',
|
||||
body:
|
||||
'We understand the emotional weight families carry during times of crisis — whether facing homelessness, domestic violence, disaster recovery, financial instability, or personal struggles that leave people feeling hopeless and alone.',
|
||||
reminder: 'This foundation was built to remind people that they matter.',
|
||||
goal:
|
||||
'Our goal is not only to provide resources, but to restore dignity, hope, human connection, and the belief that brighter days are still ahead.',
|
||||
} as const
|
||||
|
||||
export const VISION = {
|
||||
lead:
|
||||
'We envision a future where individuals and families facing hardship are met with compassion instead of judgment, support instead of silence, and hope instead of despair.',
|
||||
body:
|
||||
'Our vision is to build stronger communities where healing, restoration, and opportunity are accessible to everyone.',
|
||||
} as const
|
||||
|
||||
export const WHAT_WE_DO = [
|
||||
{
|
||||
title: 'Community Outreach',
|
||||
body: 'Providing direct support and outreach to underserved individuals and families in need.',
|
||||
},
|
||||
{
|
||||
title: 'Crisis & Fire Relief Support',
|
||||
body: 'Helping families impacted by emergencies, displacement, natural disasters, and fire-related hardships.',
|
||||
},
|
||||
{
|
||||
title: 'Support for Women & Families',
|
||||
body: 'Offering guidance, resources, and compassionate support for mothers, children, and families navigating difficult life situations.',
|
||||
},
|
||||
{
|
||||
title: 'Homelessness Support & Resource Navigation',
|
||||
body: 'Connecting individuals and families with resources, referrals, and supportive services.',
|
||||
},
|
||||
{
|
||||
title: 'Domestic Violence Advocacy',
|
||||
body: 'Supporting survivors with compassion, encouragement, and access to community resources.',
|
||||
},
|
||||
{
|
||||
title: 'Youth & Teen Mother Support',
|
||||
body: 'Empowering young mothers and youth through mentorship, encouragement, and community support.',
|
||||
},
|
||||
] as const
|
||||
|
||||
export const STORIES_OF_HOPE = {
|
||||
lead:
|
||||
'At Miracles in Motion Foundation, every outreach event, every family served, and every act of kindness represents a story of hope.',
|
||||
body:
|
||||
'From supporting families during difficult seasons to providing resources during times of crisis, we believe real change happens when communities come together with compassion and purpose.',
|
||||
closing:
|
||||
'This is more than a nonprofit organization — it is a movement built on faith, resilience, and the belief that lives can be transformed through love and support.',
|
||||
} as const
|
||||
|
||||
export const EVENTS = {
|
||||
lead:
|
||||
'Community events are where compassion meets action — outreach gatherings, resource fairs, and seasonal support drives throughout Los Angeles County.',
|
||||
body:
|
||||
'Check back for upcoming dates, or contact us to partner on an outreach event or volunteer day.',
|
||||
ctaVolunteer: '#/volunteers',
|
||||
ctaContact: '#/contact',
|
||||
} as const
|
||||
@@ -18,6 +18,9 @@
|
||||
--mim-brand-green-mid: #2d6b5c;
|
||||
--mim-brand-gold: #c5a059;
|
||||
--mim-brand-gold-bright: #d4af37;
|
||||
--mim-cream: #faf8f5;
|
||||
--mim-warm-beige: #f5f0e8;
|
||||
--mim-warm-white: #fffefb;
|
||||
--mim-focus-ring: var(--mim-brand-gold);
|
||||
--mim-shadow-brand: rgba(26, 60, 52, 0.28);
|
||||
--mim-shadow-gold: rgba(197, 160, 89, 0.32);
|
||||
@@ -49,6 +52,36 @@
|
||||
body {
|
||||
font-family: "Inter", ui-sans-serif, system-ui, sans-serif;
|
||||
font-feature-settings: 'rlig' 1, 'calt' 1;
|
||||
background-color: var(--mim-cream);
|
||||
background-image: linear-gradient(
|
||||
180deg,
|
||||
var(--mim-warm-white) 0%,
|
||||
var(--mim-cream) 40%,
|
||||
var(--mim-warm-beige) 100%
|
||||
);
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.dark body,
|
||||
body.dark {
|
||||
background: #0a0f0e;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.mim-warm-section {
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(250, 248, 245, 0.6) 0%,
|
||||
rgba(245, 240, 232, 0.9) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.dark .mim-warm-section {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.foundation-page .section-title {
|
||||
font-family: "Playfair Display", Georgia, serif;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
|
||||
@@ -55,8 +55,8 @@ export function BrandAssetsPage() {
|
||||
</li>
|
||||
<li>
|
||||
Questions:{' '}
|
||||
<a className="underline" href="mailto:contact@mim4u.org">
|
||||
contact@mim4u.org
|
||||
<a className="underline" href="mailto:info@faithforwardmiracles.org">
|
||||
info@faithforwardmiracles.org
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -362,7 +362,7 @@ const TrustBadges: React.FC = () => (
|
||||
|
||||
<div className="mt-6 pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<p className="text-xs text-gray-500">
|
||||
EIN: 12-3456789 • All donations are tax-deductible to the fullest extent allowed by law.
|
||||
EIN: 33-4887159 • All donations are tax-deductible to the fullest extent allowed by law.
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { ArrowRight, Calendar, Heart, Mail, MapPin, Users } from 'lucide-react'
|
||||
import {
|
||||
EVENTS,
|
||||
INTRO,
|
||||
MISSION,
|
||||
POPULATIONS_SERVED,
|
||||
SITE,
|
||||
STORIES_OF_HOPE,
|
||||
VISION,
|
||||
WHAT_WE_DO,
|
||||
WHY_WE_STARTED,
|
||||
} from '../../content/siteContent'
|
||||
|
||||
function PageIntro({
|
||||
eyebrow,
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
eyebrow: string
|
||||
title: string
|
||||
children: ReactNode
|
||||
}) {
|
||||
return (
|
||||
<div className="foundation-page mx-auto max-w-4xl px-4 py-12 sm:px-6 lg:px-8">
|
||||
<p className="section-eyebrow">{eyebrow}</p>
|
||||
<h1 className="section-title mt-2">{title}</h1>
|
||||
<div className="mt-6 space-y-4 text-base leading-relaxed text-neutral-700 dark:text-neutral-300">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function ContentCard({ title, children }: { title: string; children: ReactNode }) {
|
||||
return (
|
||||
<section className="card">
|
||||
<h2 className="font-serif text-xl font-semibold tracking-tight text-primary-800 dark:text-primary-100">
|
||||
{title}
|
||||
</h2>
|
||||
<div className="mt-3 space-y-3 text-sm leading-relaxed text-neutral-700 dark:text-neutral-300">
|
||||
{children}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export function AboutPage() {
|
||||
return (
|
||||
<div className="pb-16">
|
||||
<PageIntro eyebrow={SITE.tagline} title="About Us">
|
||||
<p className="text-lg font-medium text-primary-800 dark:text-primary-100">{SITE.brandMessage}</p>
|
||||
<p>{INTRO.lead}</p>
|
||||
<p>{INTRO.body}</p>
|
||||
<p>{INTRO.belief}</p>
|
||||
<p>{INTRO.scope}</p>
|
||||
<p className="font-medium italic text-primary-700 dark:text-secondary-300">{INTRO.restoration}</p>
|
||||
<p className="text-secondary-700 dark:text-secondary-400">{SITE.closingLine}</p>
|
||||
</PageIntro>
|
||||
|
||||
<div className="mx-auto max-w-4xl space-y-6 px-4 sm:px-6 lg:px-8">
|
||||
<ContentCard title="Who we serve">
|
||||
<ul className="list-disc space-y-2 pl-5">
|
||||
{POPULATIONS_SERVED.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
</ContentCard>
|
||||
|
||||
<ContentCard title="Why we started">
|
||||
<p>{WHY_WE_STARTED.lead}</p>
|
||||
<p>{WHY_WE_STARTED.body}</p>
|
||||
<p className="font-medium">{WHY_WE_STARTED.reminder}</p>
|
||||
<p>{WHY_WE_STARTED.goal}</p>
|
||||
</ContentCard>
|
||||
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<a href="#/mission" className="btn-primary">
|
||||
Our mission <ArrowRight className="ml-1 h-4 w-4" />
|
||||
</a>
|
||||
<a href="#/what-we-do" className="btn-secondary">
|
||||
What we do
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function MissionPage() {
|
||||
return (
|
||||
<div className="pb-16" id="mission">
|
||||
<PageIntro eyebrow="Our purpose" title="Our Mission">
|
||||
<p>{MISSION.statement}</p>
|
||||
<p>{MISSION.dedication}</p>
|
||||
</PageIntro>
|
||||
|
||||
<div className="mx-auto max-w-4xl space-y-6 px-4 sm:px-6 lg:px-8">
|
||||
<ContentCard title="Our vision">
|
||||
<p>{VISION.lead}</p>
|
||||
<p>{VISION.body}</p>
|
||||
</ContentCard>
|
||||
<a href="#/donate" className="btn-primary inline-flex">
|
||||
<Heart className="mr-2 h-4 w-4" /> Support our mission
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function WhatWeDoPage() {
|
||||
return (
|
||||
<div className="pb-16">
|
||||
<PageIntro eyebrow="Programs & services" title="What We Do">
|
||||
<p>
|
||||
Compassionate, practical support for vulnerable individuals and families — from outreach and
|
||||
advocacy to emergency relief and resource navigation.
|
||||
</p>
|
||||
</PageIntro>
|
||||
|
||||
<div className="mx-auto grid max-w-4xl gap-6 px-4 sm:px-6 sm:grid-cols-2 lg:px-8">
|
||||
{WHAT_WE_DO.map((item) => (
|
||||
<article key={item.title} className="card card-hover">
|
||||
<h2 className="font-semibold tracking-tight text-primary-800 dark:text-primary-100">
|
||||
{item.title}
|
||||
</h2>
|
||||
<p className="mt-2 text-sm leading-relaxed text-neutral-700 dark:text-neutral-300">
|
||||
{item.body}
|
||||
</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mx-auto mt-10 max-w-4xl px-4 text-center sm:px-6 lg:px-8">
|
||||
<a href="#/request-assistance" className="btn-secondary mr-3">
|
||||
Request assistance
|
||||
</a>
|
||||
<a href="#/volunteers" className="btn-primary">
|
||||
<Users className="mr-2 inline h-4 w-4" /> Volunteer
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function EventsPage() {
|
||||
return (
|
||||
<div className="pb-16">
|
||||
<PageIntro eyebrow="Community" title="Community Events">
|
||||
<p>{EVENTS.lead}</p>
|
||||
<p>{EVENTS.body}</p>
|
||||
</PageIntro>
|
||||
|
||||
<div className="mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="card flex flex-col items-center gap-4 py-12 text-center">
|
||||
<Calendar className="h-12 w-12 text-secondary-500" aria-hidden />
|
||||
<p className="max-w-md text-sm text-neutral-600 dark:text-neutral-400">
|
||||
Event listings will be posted here as dates are confirmed. We welcome volunteers and
|
||||
community partners.
|
||||
</p>
|
||||
<div className="flex flex-wrap justify-center gap-3">
|
||||
<a href={EVENTS.ctaVolunteer} className="btn-primary">
|
||||
Volunteer
|
||||
</a>
|
||||
<a href={EVENTS.ctaContact} className="btn-secondary">
|
||||
Contact us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function ContactPage() {
|
||||
return (
|
||||
<div className="pb-16">
|
||||
<PageIntro eyebrow="Reach out" title="Contact Us">
|
||||
<p>
|
||||
We would love to hear from you — whether you need support, want to volunteer, or hope to
|
||||
partner with our foundation.
|
||||
</p>
|
||||
</PageIntro>
|
||||
|
||||
<div className="mx-auto max-w-4xl space-y-6 px-4 sm:px-6 lg:px-8">
|
||||
<div className="card space-y-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<Mail className="mt-0.5 h-5 w-5 shrink-0 text-primary-600 dark:text-secondary-400" />
|
||||
<div>
|
||||
<div className="font-medium">Email</div>
|
||||
<a className="text-primary-700 underline dark:text-secondary-300" href={SITE.emailHref}>
|
||||
{SITE.email}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<MapPin className="mt-0.5 h-5 w-5 shrink-0 text-primary-600 dark:text-secondary-400" />
|
||||
<div>
|
||||
<div className="font-medium">Service area</div>
|
||||
<p className="text-sm text-neutral-700 dark:text-neutral-300">{SITE.serviceArea}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<a href={SITE.emailHref} className="btn-primary">
|
||||
<Mail className="mr-2 h-4 w-4" /> Send email
|
||||
</a>
|
||||
<a href="#/request-assistance" className="btn-secondary">
|
||||
Request assistance
|
||||
</a>
|
||||
<a href="#/donate" className="btn-secondary">
|
||||
Donate
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p className="text-center text-xs text-neutral-500 dark:text-neutral-400">
|
||||
{SITE.name} · {SITE.legalStatus} · EIN {SITE.ein}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function StoriesIntroBlock() {
|
||||
return (
|
||||
<div className="card mb-8 border-secondary-200/60 bg-secondary-50/40 dark:border-secondary-800/40 dark:bg-secondary-900/20">
|
||||
<p>{STORIES_OF_HOPE.lead}</p>
|
||||
<p className="mt-3">{STORIES_OF_HOPE.body}</p>
|
||||
<p className="mt-3 italic text-primary-800 dark:text-primary-100">{STORIES_OF_HOPE.closing}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export {
|
||||
AboutPage,
|
||||
ContactPage,
|
||||
EventsPage,
|
||||
MissionPage,
|
||||
StoriesIntroBlock,
|
||||
WhatWeDoPage,
|
||||
} from './FoundationPages'
|
||||
Reference in New Issue
Block a user