Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 7 additions & 2 deletions app/src/Router.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createBrowserRouter, Navigate, RouterProvider } from 'react-router-dom';
import Layout from './components/Layout';
import DashBoardPage from './pages/Dashboard.page';
import HomePage from './pages/Home.page';
import PoliciesPage from './pages/Policies.page';
import PopulationsPage from './pages/Populations.page';
Expand Down Expand Up @@ -42,6 +43,10 @@ const router = createBrowserRouter(
},
],
},
{
index: true,
element: <HomePage />,
},
// Routes that benefit from metadata but don't require it (lazy loader)
{
element: <MetadataLazyLoader />,
Expand All @@ -50,10 +55,10 @@ const router = createBrowserRouter(
element: <Layout />,
children: [
{
index: true,
path: 'app/dashboard',
// TODO: Move HomePage out of Layout once actual static homepage is merged
// Currently HomePage has calculator navigation buttons so needs Layout
element: <HomePage />,
element: <DashBoardPage />,
},
{
path: 'reports',
Expand Down
228 changes: 228 additions & 0 deletions app/src/components/shared/HomeHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import React, { useEffect, useState } from 'react';
import { IconChevronDown } from '@tabler/icons-react';
import { useNavigate } from 'react-router-dom';
import {
Anchor,
Box,
Burger,
Button /*ButtonProps,*/,
Container,
Drawer,
Group,
Menu,
Stack,
Text,
UnstyledButton,
} from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import PolicyEngineLogo from '@/assets/policyengine-logo.svg';
import { colors, spacing, typography } from '@/designTokens';
import { useCurrentCountry } from '@/hooks/useCurrentCountry';

//type ActionButtonProps = ButtonProps & React.ButtonHTMLAttributes<HTMLButtonElement>;

/*const ActionButton: React.FC<ActionButtonProps> = (props) => (
<Button
variant="subtle"
size="sm"
fw={typography.fontWeight.medium}
c={colors.text.inverse}
{...props}
/>
);*/

const HeaderNavigation: React.FC = () => {
const [opened, { open, close }] = useDisclosure(false);

const [isScrolled, setIsScrolled] = useState(false);

useEffect(() => {
const handleScroll = () => setIsScrolled(window.scrollY > 50);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);

interface NavLink {
label: string;
path: string;
}

const countryId = useCurrentCountry();
const links: NavLink[] = [
{ label: 'Research', path: `/${countryId}/app/research` },
{ label: 'About', path: `/${countryId}/app/about` },
{ label: 'Donate', path: `/${countryId}/app/donate` },
];

const navigate = useNavigate();

return (
<Box
px={{ xs: spacing.md, sm: spacing['2xl'] }}
py={spacing.sm}
style={{
position: 'sticky',
top: isScrolled ? 0 : spacing['3xl'],
margin: isScrolled ? 0 : '0 auto',
width: isScrolled ? '100%' : '85%',
height: spacing.layout.header,
backgroundColor: colors.primary[600],
borderRadius: isScrolled ? 0 : spacing.radius.lg,
borderBottom: `0.5px solid ${colors.border.dark}`,
boxShadow: `
0px 2px 4px -1px rgba(0, 0, 0, 0.06),
0px 4px 6px -1px rgba(0, 0, 0, 0.10)
`,
zIndex: 1000,
fontFamily: typography.fontFamily.primary,
opacity: opened ? 0 : 1,
transition: 'all 0.1s ease',
}}
>
<Container size="xl" h="100%">
<Group justify="space-between" h="100%">
<Group>
{/* Logo and Main Navigation*/}
<Box mr={spacing.md} style={{ display: 'flex', alignItems: 'center' }}>
<img
src={PolicyEngineLogo}
alt="PolicyEngine"
style={{
height: spacing['3xl'],
width: 'auto',
marginRight: 12,
}}
/>
</Box>

<Group gap={spacing['3xl']} visibleFrom="lg">
{links.map((link) => (
<Anchor
key={link.label}
c={colors.text.inverse}
variant="subtle"
td="none"
fw={typography.fontWeight.medium}
size="sm"
onClick={() => navigate(link.path)}
>
{link.label}
</Anchor>
))}

<Menu shadow="md" width={200} zIndex={1001} position="bottom" offset={10}>
<Menu.Target>
<UnstyledButton>
<Group gap={4}>
<Text c={colors.text.inverse} fw={typography.fontWeight.medium} size="sm">
Learn
</Text>
<IconChevronDown size={16} color={colors.text.inverse} />
</Group>
</UnstyledButton>
</Menu.Target>
<Menu.Dropdown>
{[
'AI & ML',
'API',
'Microsimulation',
'Benefit Access',
'Educational Use',
'Open Source',
].map((item) => (
<Menu.Item key={item}>{item}</Menu.Item>
))}
</Menu.Dropdown>
</Menu>
</Group>
</Group>

{/* Action Buttons */}
<Group gap={spacing.sm} visibleFrom="lg">
{/*<ActionButton>Log In</ActionButton>*/}
<Button
style={{ backgroundColor: colors.warning, borderRadius: spacing.radius.md }}
c={colors.text.primary}
fw={typography.fontWeight.semibold}
size="sm"
>
Sign Up
</Button>
</Group>

{/* Mobile Burger Menu */}
<Group hiddenFrom="lg">
<Burger opened={opened} onClick={open} color={colors.text.inverse} size="sm" />
</Group>
</Group>
</Container>

{/* Mobile Drawer */}
<Drawer
opened={opened}
onClose={close}
position="right"
size="sm"
styles={{
content: { backgroundColor: colors.primary[600] },
header: { backgroundColor: colors.primary[600], borderBottom: 'none' },
}}
closeButtonProps={{ style: { color: colors.text.inverse }, size: 'md' }}
>
<Stack gap={spacing.lg} p={spacing.lg}>
{links.map((link) => (
<Anchor
key={link.label}
c={colors.text.inverse}
variant="subtle"
td="none"
fw={typography.fontWeight.medium}
size="sm"
onClick={() => navigate(link.path)}
>
{link.label}
</Anchor>
))}

<Box>
<Text c={colors.text.inverse} fw={typography.fontWeight.semibold} mb={spacing.sm}>
Learn
</Text>
<Stack gap={spacing.xs} ml={spacing.md}>
{[
'AI & ML',
'API',
'Microsimulation',
'Benefit Access',
'Educational Use',
'Open Source',
].map((item) => (
<Text key={item} c={colors.text.inverse} size="sm" onClick={close}>
{item}
</Text>
))}
</Stack>
</Box>

<Box pt={spacing.lg} style={{ borderTop: `1px solid ${colors.border.light}` }}>
{/*<ActionButton fullWidth mb={spacing.sm} onClick={close}>
Log In
</ActionButton>*/}
<Button
style={{ backgroundColor: colors.warning, borderRadius: spacing.radius.md }}
c={colors.text.primary}
fw={typography.fontWeight.semibold}
mb={spacing.sm}
fullWidth
onClick={close}
>
Sign Up
</Button>
</Box>
</Stack>
</Drawer>
</Box>
);
};

export default HeaderNavigation;
Binary file added app/src/images/logos/orgs/cgo.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 app/src/images/logos/orgs/epmt.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 app/src/images/logos/orgs/f4gi.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 app/src/images/logos/orgs/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 app/src/images/logos/orgs/myfriendben.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 app/src/images/logos/orgs/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 app/src/images/logos/orgs/pn3policy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions app/src/pages/Dashboard.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { Button } from '@mantine/core';
import FlowContainer from '@/components/FlowContainer';
import { PolicyCreationFlow } from '@/flows/policyCreationFlow';
import { PolicyViewFlow } from '@/flows/policyViewFlow';
import { PopulationCreationFlow } from '@/flows/populationCreationFlow';
import { PopulationViewFlow } from '@/flows/populationViewFlow';
import { ReportCreationFlow } from '@/flows/reportCreationFlow';
import { ReportViewFlow } from '@/flows/reportViewFlow';
import { SimulationCreationFlow } from '@/flows/simulationCreationFlow';
import { SimulationViewFlow } from '@/flows/simulationViewFlow';
import { clearFlow, setFlow } from '../reducers/flowReducer';

export default function DashBoardPage() {
const dispatch = useDispatch();
const navigate = useNavigate();

// Note: Below is for testing purposes only
return (
<>
<h1>TODO: Home Page</h1>
<Button variant="default" onClick={() => dispatch(clearFlow())}>
Clear all flows
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(PolicyCreationFlow))}>
Execute policy creation flow
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(PolicyViewFlow))}>
Show Policy View
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(SimulationCreationFlow))}>
Execute simulation creation flow
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(SimulationViewFlow))}>
Show Simulation View
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(PopulationCreationFlow))}>
Execute Population Flow
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(PopulationViewFlow))}>
View Populations
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(ReportCreationFlow))}>
Execute Report Creation Flow (TEST)
</Button>
<Button variant="default" onClick={() => dispatch(setFlow(ReportViewFlow))}>
Show Report View
</Button>
<Button variant="default" onClick={() => navigate('/us/report-output-demo')}>
View Society-Wide Report Output (Demo)
</Button>
<Button variant="default" onClick={() => navigate('/us/household-output-demo')}>
View Household Report Output (Demo)
</Button>
<FlowContainer />
</>
);
}
Loading
Loading