Files
Ehsan/artifacts/ehsan-poc/src/pages/about.tsx
T
Replit Agent 45a52b177f Add About EHSAN dropdown nav + About page
Task #15: Make «عن إحسان» top-nav a real dropdown and build the About page.

- Header.tsx: converted static «عن إحسان» span into a dropdown trigger
  replicating the existing services dropdown pattern (aboutOpen state,
  trigger/panel refs, outside-click + Escape handling). Desktop panel and
  mobile nav both list «من نحن» (/about) and «اللجان» (/about/committees).
- New pages/about.tsx: green intro panel («نبذة عن إحسان») + tab strip
  (الرؤية والرسالة / الأهداف والركائز / المزايا والمجالات) for the Who-we-are
  view, and a committee card grid for the Committees view. Section chosen via
  /about/:section? route param; in-page toggle between the two. Reuses Reveal
  for scroll-in.
- App.tsx: registered <Route path="/about/:section?" component={About} />.
- translations.ts: added full bilingual `about` section (AR + EN).

Fully bilingual via existing t.* system, RTL verified, no emojis.
tsc passes; screenshots confirm both views render correctly.
2026-06-05 19:30:47 +00:00

166 lines
6.2 KiB
TypeScript

import { useState } from "react";
import { useParams, Link } from "wouter";
import { useLanguage } from "../contexts/LanguageContext";
import { Reveal } from "../components/Reveal";
import { Card, CardContent } from "@/components/ui/card";
import { Users, Info, Check, Building2 } from "lucide-react";
type TabKey = "visionMission" | "goalsPillars" | "advantagesDomains";
function ListBlock({ title, items }: { title: string; items: string[] }) {
return (
<div>
<h3 className="text-lg font-bold text-primary mb-4">{title}</h3>
<ul className="space-y-3">
{items.map((item, i) => (
<li key={i} className="flex items-start gap-3">
<Check className="w-5 h-5 text-primary shrink-0 mt-0.5" />
<span className="text-foreground/90 leading-relaxed">{item}</span>
</li>
))}
</ul>
</div>
);
}
function StatementBlock({ title, text }: { title: string; text: string }) {
return (
<div>
<h3 className="text-lg font-bold text-primary mb-3">{title}</h3>
<p className="text-foreground/90 leading-loose">{text}</p>
</div>
);
}
export default function About() {
const { t } = useLanguage();
const params = useParams<{ section?: string }>();
const isCommittees = params.section === "committees";
const [tab, setTab] = useState<TabKey>("visionMission");
const tabs: { key: TabKey; label: string }[] = [
{ key: "visionMission", label: t.about.tabVisionMission },
{ key: "goalsPillars", label: t.about.tabGoalsPillars },
{ key: "advantagesDomains", label: t.about.tabAdvantagesDomains },
];
return (
<div className="container mx-auto px-4 py-10">
{/* Section toggle: Who we are / Committees */}
<div className="flex justify-end mb-8">
<div className="inline-flex rounded-full border border-border bg-muted/40 p-1">
<Link
href="/about"
className={`inline-flex items-center gap-2 rounded-full px-5 py-2 text-sm font-medium transition-colors ${
!isCommittees
? "bg-primary/10 text-primary"
: "text-muted-foreground hover:text-primary"
}`}
data-testid="about-tab-whoWeAre"
>
<Info className="w-4 h-4" />
{t.about.whoWeAre}
</Link>
<Link
href="/about/committees"
className={`inline-flex items-center gap-2 rounded-full px-5 py-2 text-sm font-medium transition-colors ${
isCommittees
? "bg-primary/10 text-primary"
: "text-muted-foreground hover:text-primary"
}`}
data-testid="about-tab-committees"
>
<Users className="w-4 h-4" />
{t.about.committees}
</Link>
</div>
</div>
{isCommittees ? (
<Reveal>
<h1 className="text-2xl font-bold text-foreground mb-3">{t.about.committeesTitle}</h1>
<p className="text-muted-foreground mb-8 max-w-3xl leading-relaxed">
{t.about.committeesIntro}
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{t.about.committeeItems.map((c, i) => (
<Reveal key={i} delay={(i % 2) * 0.08} className="h-full">
<Card className="h-full">
<CardContent className="p-6 flex items-start gap-4">
<div className="w-11 h-11 rounded-xl bg-primary/10 text-primary flex items-center justify-center shrink-0">
<Building2 className="w-5 h-5" />
</div>
<div>
<h3 className="text-base font-bold text-foreground mb-1">{c.name}</h3>
<p className="text-sm text-muted-foreground leading-relaxed">{c.desc}</p>
</div>
</CardContent>
</Card>
</Reveal>
))}
</div>
</Reveal>
) : (
<>
{/* Intro green panel */}
<Reveal>
<section className="rounded-2xl bg-primary text-primary-foreground p-8 md:p-12 mb-10">
<h1 className="text-2xl md:text-3xl font-bold mb-5">{t.about.introTitle}</h1>
<p className="leading-loose text-primary-foreground/90 max-w-4xl">
{t.about.intro}
</p>
</section>
</Reveal>
{/* Tabs */}
<Reveal>
<div className="border-b border-border mb-8">
<div className="flex flex-wrap gap-2">
{tabs.map((tb) => (
<button
key={tb.key}
type="button"
onClick={() => setTab(tb.key)}
data-testid={`about-section-${tb.key}`}
className={`px-4 py-3 text-sm font-medium border-b-2 -mb-px transition-colors ${
tab === tb.key
? "border-primary text-primary"
: "border-transparent text-muted-foreground hover:text-primary"
}`}
>
{tb.label}
</button>
))}
</div>
</div>
</Reveal>
{/* Tab content */}
<Reveal>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12">
{tab === "visionMission" && (
<>
<StatementBlock title={t.about.visionTitle} text={t.about.visionText} />
<StatementBlock title={t.about.missionTitle} text={t.about.missionText} />
</>
)}
{tab === "goalsPillars" && (
<>
<ListBlock title={t.about.goalsTitle} items={t.about.goals} />
<ListBlock title={t.about.pillarsTitle} items={t.about.pillars} />
</>
)}
{tab === "advantagesDomains" && (
<>
<ListBlock title={t.about.advantagesTitle} items={t.about.advantages} />
<ListBlock title={t.about.domainsTitle} items={t.about.domains} />
</>
)}
</div>
</Reveal>
</>
)}
</div>
);
}