Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/PolicyEngine.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Research from "./pages/Research";
import About from "./pages/About";
import Jobs from "./pages/Jobs";
import Supporters from "./pages/Supporters";
import Users from "./pages/Users";
import {
Navigate,
Outlet,
Expand Down Expand Up @@ -324,6 +325,7 @@ export default function PolicyEngine() {
<Route path="about" element={<About />} />
<Route path="jobs" element={<Jobs />} />
<Route path="supporters" element={<Supporters />} />
<Route path="users" element={<Users />} />
<Route path="testimonials" element={<Testimonials />} />
<Route path="calculator" element={<CalculatorInterstitial />} />
<Route path="simulations" element={<SimulationsPage />} />
Expand Down
104 changes: 104 additions & 0 deletions src/data/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// User organizations that have used PolicyEngine for policy analysis and research

import NiskanenCenter from "../images/logos/users/niskanen-center.png";
import JEC from "../images/logos/users/jec.png";
import NBER from "../images/logos/users/nber.png";
import Georgetown from "../images/logos/users/georgetown.png";
import UMichigan from "../images/logos/users/umich.png";
import USC from "../images/logos/users/usc.png";
import UHawaii from "../images/logos/users/hawaii.png";
import PN3Policy from "../images/logos/users/pn3policy.png";
import NewYorkSenate from "../images/logos/users/ny-senate.png";
import MarylandChildAlliance from "../images/logos/users/mca.jpg";

export const users = [
{
id: "niskanen-center",
name: "Niskanen Center",
logo: NiskanenCenter,
website: "https://www.niskanencenter.org/",
description:
"A center-right think tank focused on pragmatic policy solutions",
category: "think-tank",
},
{
id: "joint-economic-committee",
name: "Joint Economic Committee",
logo: JEC,
website: "https://www.jec.senate.gov/",
description: "A bipartisan committee of the U.S. Congress",
category: "government",
},
{
id: "nber",
name: "National Bureau of Economic Research",
logo: NBER,
website: "https://www.nber.org/",
description: "America's leading nonprofit economic research organization",
category: "research",
},
{
id: "georgetown",
name: "Georgetown University",
logo: Georgetown,
website: "https://www.georgetown.edu/",
description: "Leading research university with expertise in public policy",
category: "academic",
},
{
id: "university-michigan",
name: "University of Michigan",
logo: UMichigan,
website: "https://umich.edu/",
description: "Public research university with renowned economics programs",
category: "academic",
},
{
id: "usc",
name: "University of Southern California",
logo: USC,
website: "https://www.usc.edu/",
description: "Private research university with strong policy programs",
category: "academic",
},
{
id: "university-hawaii",
name: "University of Hawaii",
logo: UHawaii,
website: "https://www.hawaii.edu/",
description: "State university system focused on policy research",
category: "academic",
},
{
id: "prenatal-to-3-policy-impact-center",
name: "Prenatal-to-3 Policy Impact Center",
logo: PN3Policy,
website: "https://pn3policy.org/",
description: "Research center focused on early childhood policy",
category: "research",
},
{
id: "new-york-senate",
name: "New York Senate",
logo: NewYorkSenate,
website: "https://www.nysenate.gov/",
description: "Upper chamber of the New York State Legislature",
category: "government",
},
{
id: "maryland-child-alliance",
name: "Maryland Child Alliance",
logo: MarylandChildAlliance,
website: "https://www.marylandchildalliance.org/",
description: "Advocacy organization for children and families in Maryland",
category: "advocacy",
},
];

export const userCategories = {
government: "Government Agencies",
"think-tank": "Think Tanks",
research: "Research Organizations",
academic: "Academic Institutions",
advocacy: "Advocacy Organizations",
};
Binary file added src/images/logos/users/georgetown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/hawaii.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/jec.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/mca.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/nber.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/niskanen-center.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/ny-senate.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/pn3policy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/umich.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/logos/users/usc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/layout/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
TeamOutlined,
UserAddOutlined,
BankOutlined,
UsergroupAddOutlined,
} from "@ant-design/icons";
import { loginOptions, logoutOptions } from "../auth/authUtils";
import { Dropdown } from "antd";
Expand Down Expand Up @@ -71,6 +72,11 @@ export const ABOUT_DROPDOWN_LINKS = [
link: "about",
icon: <TeamOutlined />,
},
{
title: "Users",
link: "users",
icon: <UsergroupAddOutlined />,
},
{
title: "Careers",
link: "jobs",
Expand Down
200 changes: 200 additions & 0 deletions src/pages/Users.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import Header from "../layout/Header.jsx";
import Footer from "../layout/Footer.jsx";
import Section from "../layout/Section.jsx";
import style from "../style/index.js";
import PageHeader from "../layout/PageHeader.jsx";
import { users, userCategories } from "../data/users.js";
import useDisplayCategory from "../hooks/useDisplayCategory.js";

Copilot AI Aug 4, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The useDisplayCategory hook is imported but the component Users is not using it. Only the UserCard component uses this hook. Consider moving this import to the UserCard component or removing it from the top-level imports.

Suggested change
import useDisplayCategory from "../hooks/useDisplayCategory.js";

Copilot uses AI. Check for mistakes.
import { Helmet } from "react-helmet";

export default function Users() {
// Group users by category
const usersByCategory = users.reduce((acc, user) => {
if (!acc[user.category]) {
acc[user.category] = [];
}
acc[user.category].push(user);
return acc;
}, {});

return (
<>
<Helmet>
<title>Our Users | PolicyEngine</title>
<meta
name="description"
content="Organizations and institutions using PolicyEngine for policy analysis and research, including government agencies, think tanks, universities, and advocacy groups."
/>
</Helmet>
<div>
<Header />
<PageHeader title="Our users" backgroundColor={style.colors.BLUE_98}>
<p style={{ margin: 0 }}>
PolicyEngine is trusted by government agencies, think tanks,
universities, and advocacy organizations to provide rigorous policy
analysis and evidence-based research.
</p>
</PageHeader>

{/* Hero section with blended logos - placeholder for now */}
<Section backgroundColor={style.colors.WHITE}>
<div
style={{
textAlign: "center",
padding: "40px 0",
backgroundColor: style.colors.LIGHT_GRAY_98,
marginBottom: "40px",
borderRadius: "8px",
}}
>
<div
style={{
height: "200px",
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: "18px",
color: style.colors.DARK_GRAY,
}}
>
[Blended user logos will be displayed here]
</div>
</div>
</Section>

{/* User categories */}
{Object.entries(userCategories).map(([categoryKey, categoryName]) => {
const categoryUsers = usersByCategory[categoryKey];
if (!categoryUsers || categoryUsers.length === 0) return null;

return (
<Section
key={categoryKey}
backgroundColor={
categoryKey === "government"
? style.colors.BLUE
: style.colors.WHITE
}
>
<h2
style={{
color:
categoryKey === "government"
? style.colors.WHITE
: style.colors.BLACK,
marginBottom: "30px",
}}
>
{categoryName}
</h2>
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
gap: "30px",
}}
>
{categoryUsers.map((user) => (
<UserCard
key={user.id}
user={user}
inverted={categoryKey === "government"}
/>
))}
</div>
</Section>
);
})}

<Footer />
</div>
</>
);
}

function UserCard({ user, inverted = false }) {
const displayCategory = useDisplayCategory();
const isMobile = displayCategory === "mobile";

const cardStyle = {
display: "flex",
flexDirection: isMobile ? "column" : "row",
alignItems: isMobile ? "center" : "flex-start",
padding: "20px",
backgroundColor: inverted ? style.colors.BLUE : style.colors.WHITE,
border: inverted
? `1px solid ${style.colors.LIGHT_BLUE}`
: `1px solid ${style.colors.LIGHT_GRAY}`,
borderRadius: "8px",
boxShadow: "0 2px 4px rgba(0,0,0,0.05)",
textAlign: isMobile ? "center" : "left",
};

const logoStyle = {
width: "120px",
height: "80px",
objectFit: "contain",
marginRight: isMobile ? 0 : "20px",
marginBottom: isMobile ? "15px" : 0,
};

const textStyle = {
color: inverted ? style.colors.WHITE : style.colors.BLACK,
};

return (
<div style={cardStyle}>
{user.logo && (
<a
href={user.website}
target="_blank"
rel="noopener noreferrer"
aria-label={`Visit ${user.name} website`}
>
<img src={user.logo} alt={`${user.name} logo`} style={logoStyle} />
</a>
)}
<div>
<h3
style={{
...textStyle,
margin: "0 0 8px 0",
fontSize: "18px",
}}
>
{user.website ? (
<a
href={user.website}
target="_blank"
rel="noopener noreferrer"
style={{
color: inverted ? style.colors.WHITE : style.colors.BLUE,
textDecoration: "none",
}}
onMouseEnter={(e) => {
e.target.style.textDecoration = "underline";
}}
onMouseLeave={(e) => {
e.target.style.textDecoration = "none";
}}
Comment on lines +150 to +159

Copilot AI Aug 4, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inline event handlers with style mutations can cause performance issues and make the code harder to maintain. Consider using CSS :hover pseudo-class or a proper state management approach for hover effects instead of directly manipulating the DOM.

Suggested change
style={{
color: inverted ? style.colors.WHITE : style.colors.BLUE,
textDecoration: "none",
}}
onMouseEnter={(e) => {
e.target.style.textDecoration = "underline";
}}
onMouseLeave={(e) => {
e.target.style.textDecoration = "none";
}}
className="user-link"
style={{
color: inverted ? style.colors.WHITE : style.colors.BLUE,
textDecoration: "none",
}}

Copilot uses AI. Check for mistakes.
>
{user.name}
</a>
) : (
user.name
)}
</h3>
<p
style={{
...textStyle,
margin: 0,
fontSize: "14px",
lineHeight: "1.4",
}}
>
{user.description}
</p>
</div>
</div>
);
}
Loading