Skip to content

Commit

Permalink
Interactive map (#15)
Browse files Browse the repository at this point in the history
* map basics done

* map page styling

* chapter info

* state text

* modal content changed to buttons of chapters, with clicking showing either form or no form text

* header fixed + colors fixed

* fixing lint

* dummy data

* merge conflicts

* adding routing for chapter login on map landing page

---------

Co-authored-by: Jihun (James) Doh <[email protected]>
Co-authored-by: kygchng <[email protected]>
  • Loading branch information
3 people authored Jan 25, 2025
1 parent 067f027 commit 60385d9
Show file tree
Hide file tree
Showing 11 changed files with 964 additions and 685 deletions.
8 changes: 5 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write 'src/**/*.{js,jsx,ts,tsx}' ",
"lint": "eslint --fix 'src/**/*.{js,jsx,ts,tsx} .'",
"lint": "eslint --fix 'src/**/*.{js,jsx,ts,tsx}'",
"postinstall": "echo \"Package install attempted in client directory\""
},
"eslintConfig": {
Expand All @@ -33,7 +33,8 @@
]
},
"dependencies": {
"@emotion/styled": "^11.13.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@material-ui/icons": "^4.11.2",
"@mui/material": "^5.5.3",
"@mui/system": "^5.5.2",
Expand All @@ -46,14 +47,15 @@
"react-redux": "^8.0.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"react-usa-map": "^1.5.0",
"redux": "^4.1.2",
"redux-persist": "^6.0.0",
"styled-components": "^5.3.5",
"typeface-hk-grotesk": "^1.0.0",
"web-vitals": "^3.0.3"
},
"devDependencies": {
"@mui/styled-engine": "npm:@mui/styled-engine-sc@latest",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
Expand Down
Binary file added client/public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import EmailResetPasswordPage from './Authentication/EmailResetPasswordPage.tsx'
import ResetPasswordPage from './Authentication/ResetPasswordPage.tsx';
import AlertPopup from './components/AlertPopup.tsx';
import InviteRegisterPage from './Authentication/InviteRegisterPage.tsx';
import Landing from './Landing/Landing.tsx';
import TempAdminDashboardPage from './AdminDashboard/TempAdminDashboardPage.tsx';

function App() {
Expand All @@ -34,6 +35,7 @@ function App() {
<CssBaseline>
<AlertPopup />
<Routes>
<Route path="/" element={<Landing />} />
{/* Routes accessed only if user is not authenticated */}
<Route element={<UnauthenticatedRoutesWrapper />}>
<Route path="/login" element={<LoginPage />} />
Expand Down
4 changes: 2 additions & 2 deletions client/src/Authentication/RegisterPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ function RegisterPage() {
</Grid>
<FormRow>
<Grid container justifyContent="center">
<Link component={RouterLink} to="../">
Back to Login
<Link component={RouterLink} to="/home">
Back to Home
</Link>
</Grid>
</FormRow>
Expand Down
294 changes: 294 additions & 0 deletions client/src/Home/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
import React, { useState } from 'react';
import {
Button,
Dialog,
DialogTitle,
DialogContent,
IconButton,
Typography,
Box,
List,
ListItem,
Paper,
} from '@mui/material';

function CloseIcon() {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
);
}

interface StateCategory {
color: string;
hoverColor: string;
states: string[];
}

interface StateCategories {
[key: string]: StateCategory;
}

interface Chapter {
city: string;
id: string;
}

interface StateData {
name: string;
acceptingRequests: boolean;
chapters: Chapter[];
}

interface StateChapters {
[key: string]: StateData;
}

const stateCategories: StateCategories = {
turquoise: {
color: '#7ACCC8',
hoverColor: '#5FB9B5',
states: ['CA', 'ID', 'CO', 'ND', 'IA', 'MI', 'PA', 'GA', 'TX'],
},
yellow: {
color: '#FFE17B',
hoverColor: '#EBD068',
states: ['AZ', 'NE', 'WI', 'LA', 'NJ', 'HI'],
},
salmon: {
color: '#F7BDB1',
hoverColor: '#E4AAA0',
states: ['WA', 'NV', 'WY', 'MN', 'IL', 'KY', 'AL'],
},
inactive: {
color: '#D3D3D3',
hoverColor: '#C0C0C0',
states: [
'OR',
'MT',
'UT',
'SD',
'KS',
'MO',
'TN',
'NC',
'SC',
'VA',
'WV',
'OH',
'IN',
'MS',
'AR',
'OK',
'NM',
'ME',
'NH',
'VT',
'MA',
'RI',
'CT',
'NY',
'DE',
'MD',
'FL',
'AK',
],
},
};

const stateChapters: StateChapters = {
WI: {
name: 'Wisconsin',
acceptingRequests: true,
chapters: [
{ city: 'Columbia County', id: 'wi-1' },
{ city: 'DeForest', id: 'wi-2' },
{ city: 'Madison', id: 'wi-3' },
{ city: 'Sun Prairie', id: 'wi-4' },
{ city: 'Poynette', id: 'wi-5' },
],
},
};

export default function LandingPage() {
const [selectedState, setSelectedState] = useState<StateData | null>(null);
const [hoveredChapter, setHoveredChapter] = useState<Chapter | null>(null);

const mapHandler = (event: any) => {
const stateData = stateChapters[event.target.dataset.name];
if (stateData) {
setSelectedState(stateData);
}
};

const statesCustomConfig = () => {
const config: { [key: string]: { fill: string } } = {};

Object.entries(stateCategories).forEach(([category, data]) => {
data.states.forEach((state) => {
config[state] = {
fill: data.color,
};
});
});

return config;
};

const handleRequestClick = (chapter: Chapter): void => {
console.log('Navigate to request form for:', chapter);
};

const handleClose = (): void => {
setSelectedState(null);
};

return (
<Box sx={{ minHeight: '100vh', bgcolor: 'background.paper', p: 4 }}>
{/* Header */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mb: 4,
}}
>
<Typography variant="h4" component="h1" fontWeight="bold">
Welcome!
</Typography>
<Button
variant="contained"
sx={{
bgcolor: '#EC4899',
'&:hover': {
bgcolor: '#DB2777',
},
}}
onClick={() => console.log('Navigate to login')}
>
Chapter Login
</Button>
</Box>

{/* Instructions */}
<Box sx={{ mb: 4, color: 'text.secondary' }}>
<Typography>
Click on your state below to connect with a local chapter in your
area!
</Typography>
<List sx={{ ml: 2 }}>
<ListItem sx={{ display: 'list-item' }}>
Find your local birthday hero directly in your area
</ListItem>
<ListItem sx={{ display: 'list-item' }}>
Sign up to be a volunteer
</ListItem>
<ListItem sx={{ display: 'list-item' }}>
Donate to your local chapter
</ListItem>
<ListItem sx={{ display: 'list-item' }}>
Sign up for our Milestone program
</ListItem>
<ListItem sx={{ display: 'list-item' }}>
Contact your local chapter leader to learn more ways you can support
our cause
</ListItem>
</List>
</Box>

{/* US Map */}
<Box sx={{ width: '100%', maxWidth: '4xl', mx: 'auto' }} />

{/* State Chapters Modal */}
<Dialog
open={selectedState !== null}
onClose={handleClose}
maxWidth="sm"
fullWidth
>
{selectedState && (
<>
<DialogTitle
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
{selectedState.name}
<IconButton size="small" onClick={handleClose} aria-label="close">
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent>
<Typography variant="subtitle1" sx={{ mb: 2 }}>
Local Chapters
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
{selectedState.chapters.map((chapter) => (
<Paper
key={chapter.id}
elevation={1}
sx={{
p: 2,
position: 'relative',
'&:hover': { bgcolor: 'action.hover' },
cursor: 'pointer',
}}
onMouseEnter={() => setHoveredChapter(chapter)}
onMouseLeave={() => setHoveredChapter(null)}
>
<Typography>{chapter.city}</Typography>
{hoveredChapter === chapter && (
<Box
sx={{
position: 'absolute',
right: 16,
top: '50%',
transform: 'translateY(-50%)',
}}
>
{selectedState.acceptingRequests ? (
<Button
size="small"
variant="contained"
sx={{
bgcolor: '#EC4899',
'&:hover': {
bgcolor: '#DB2777',
},
}}
onClick={() => handleRequestClick(chapter)}
>
Request Form
</Button>
) : (
<Typography color="error" variant="body2">
Sorry, we are not receiving requests. Please try
again next month!
</Typography>
)}
</Box>
)}
</Paper>
))}
</Box>
</DialogContent>
</>
)}
</Dialog>
</Box>
);
}
39 changes: 39 additions & 0 deletions client/src/Landing/Landing.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { Button } from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import LandingMap from './LandingMap.tsx';
import LandingHeader from './LandingHeader.tsx';
import { useAppSelector } from '../util/redux/hooks.ts';
import { selectUser } from '../util/redux/userSlice.ts';

export default function Landing() {
const user = useAppSelector(selectUser);
// Check if user has an email, which indicates they're logged in
const isLoggedIn = Boolean(user.email);
const loginPath = isLoggedIn ? '/home' : '/login';

return (
<div style={{ position: 'relative' }}>
<LandingHeader />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<Button
component={RouterLink}
to={loginPath}
variant="contained"
sx={{
backgroundColor: '#f28f8a',
width: '200px',
height: '50px',
fontSize: '17px',
'&:hover': {
backgroundColor: '#ff3f73',
},
}}
>
CHAPTER LOGIN
</Button>
</div>
<LandingMap />
</div>
);
}
Loading

0 comments on commit 60385d9

Please sign in to comment.