-
- Ideas {ideaCount || 0}
-
+ {this.state.showIdeasTab && (
+
+ Ideas {ideaCount || 0}
+
+ )}
My Stuff {myProjectsCount || 0}
+
+ My Votes {myVotesCount || 0}
+
{this.state.isWide && (
@@ -411,6 +424,7 @@ class ProjectList extends Component {
const showIdeas = !showParam || showParam === 'ideas';
const showProjects = showParam === 'projects';
const showMyProjects = showParam === 'my-projects';
+ const showMyVotes = showParam === 'my-votes';
let viewStyle = viewParam === 'grid' ? 'grid' : 'list';
if (!this.state.isWide) viewStyle = 'list';
@@ -430,9 +444,11 @@ class ProjectList extends Component {
showIdeas,
showProjects,
showMyProjects,
+ showMyVotes,
ideaCount: projectIdeas.length,
projectCount: actualProjects.length,
myProjectsCount: myProjects.length,
+ myVotesCount: userVotes.length,
viewStyle,
})}
@@ -516,6 +532,48 @@ class ProjectList extends Component {
)}
+ {showMyVotes && myVotedProjects.length > 0 && (
+
+ {viewStyle === 'grid' ? (
+
+ {myVotedProjects.map((project) => (
+ v.project === project.key)}
+ firebase={firebase}
+ project={project}
+ awardCategoryOptions={awardCategoryOptions}
+ awardList={awardList}
+ userList={userList}
+ group={{id: project.group, ...groupsList[project.group]}}
+ submissionsClosed={submissionsClosed}
+ isOlderYear={isOlderYear}
+ />
+ ))}
+
+ ) : (
+
+ {myVotedProjects.map((project) => (
+ v.project === project.key)}
+ firebase={firebase}
+ project={project}
+ awardCategoryOptions={awardCategoryOptions}
+ awardList={awardList}
+ userList={userList}
+ group={{id: project.group, ...groupsList[project.group]}}
+ submissionsClosed={submissionsClosed}
+ isOlderYear={isOlderYear}
+ />
+ ))}
+
+ )}
+
+ )}
+
{showProjects && (
{!!winningProjects.length && (
@@ -697,14 +755,24 @@ class ProjectList extends Component {
const showIdeas = !showParam || showParam === 'ideas';
const showProjects = showParam === 'projects';
const showMyProjects = showParam === 'my-projects';
+ const showMyVotes = showParam === 'my-votes';
let viewStyle = viewParam === 'grid' ? 'grid' : 'list';
if (!this.state.isWide) viewStyle = 'list';
+ let userVotes = year ? getAuthUserVotes(auth.uid, year.votes) : [];
+ let awardCategoryOptions = getAwardCategories(awardCategoryList);
+
const hasAnyProjects = projectsLFH.length > 0 || otherProjects.length > 0;
const hasAnyIdeas = projectIdeas.length > 0;
const hasAnyMyProjects = myProjects.length > 0;
+ const hasAnyMyVotes = userVotes.length > 0;
- let userVotes = year ? getAuthUserVotes(auth.uid, year.votes) : [];
- let awardCategoryOptions = getAwardCategories(awardCategoryList);
+ // Get projects the user has voted on
+ let myVotedProjects = [];
+ if (userVotes.length > 0) {
+ myVotedProjects = projects.filter((project) =>
+ userVotes.some((vote) => vote.project === project.key)
+ );
+ }
let emptyState = null;
if (showProjects && !hasAnyProjects) {
@@ -728,6 +796,13 @@ class ProjectList extends Component {
);
}
+ if (showMyVotes && !hasAnyMyVotes) {
+ emptyState = (
+
+ Oops! You haven't voted on any projects yet!
+
+ );
+ }
return (
@@ -735,9 +810,11 @@ class ProjectList extends Component {
showIdeas,
showProjects,
showMyProjects,
+ showMyVotes,
ideaCount: projectIdeas.length,
projectCount: projectsLFH.length + otherProjects.length,
myProjectsCount: myProjects.length,
+ myVotesCount: userVotes.length,
viewStyle,
})}
@@ -827,6 +904,48 @@ class ProjectList extends Component {
)}
+ {showMyVotes && myVotedProjects.length > 0 && (
+
+ {viewStyle === 'grid' ? (
+
+ {myVotedProjects.map((project) => (
+ v.project === project.key)}
+ firebase={firebase}
+ project={project}
+ awardCategoryOptions={awardCategoryOptions}
+ awardList={awardList}
+ userList={userList}
+ group={{id: project.group, ...groupsList[project.group]}}
+ submissionsClosed={submissionsClosed}
+ isOlderYear={isOlderYear}
+ />
+ ))}
+
+ ) : (
+
+ {myVotedProjects.map((project) => (
+ v.project === project.key)}
+ firebase={firebase}
+ project={project}
+ awardCategoryOptions={awardCategoryOptions}
+ awardList={awardList}
+ userList={userList}
+ group={{id: project.group, ...groupsList[project.group]}}
+ submissionsClosed={submissionsClosed}
+ isOlderYear={isOlderYear}
+ />
+ ))}
+
+ )}
+
+ )}
+
{showProjects && projectsLFH.length + otherProjects.length > 0 && (
{viewStyle === 'grid' ? (
From ace3cc732b4ee50e3a2a306b65aa57980d933ecb Mon Sep 17 00:00:00 2001
From: John Manhart
Date: Sun, 24 Aug 2025 13:19:26 -0700
Subject: [PATCH 3/8] Adding in more vote indicators to the project list
---
src/pages/ProjectList.css | 8 +++++++
src/pages/ProjectList.js | 48 ++++++++++++++++++++++++++++++---------
2 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/src/pages/ProjectList.css b/src/pages/ProjectList.css
index 3764daa..2c856f9 100644
--- a/src/pages/ProjectList.css
+++ b/src/pages/ProjectList.css
@@ -495,6 +495,14 @@
background: #e9d8fd; /* lavender tint */
border: 1px solid #d2bfff;
}
+.Tag--vote {
+ color: #1d1127; /* gray-100 */
+ background: #d1f2ff; /* light blue tint */
+ border: 1px solid #b5e6ff;
+}
+.Tag--vote .vote-label {
+ font-weight: 400; /* regular weight for "You Voted" */
+}
.Tag--help {
color: #1d1127;
background: #ffd1ea; /* pink tint */
diff --git a/src/pages/ProjectList.js b/src/pages/ProjectList.js
index 5680827..fe3fe8a 100644
--- a/src/pages/ProjectList.js
+++ b/src/pages/ProjectList.js
@@ -45,6 +45,7 @@ class ProjectListItem extends Component {
group: PropTypes.object,
submissionsClosed: PropTypes.bool,
isOlderYear: PropTypes.bool,
+ userVote: PropTypes.array,
};
render() {
@@ -56,6 +57,7 @@ class ProjectListItem extends Component {
userList,
group,
isOlderYear,
+ userVote,
} = this.props;
let link =
currentYear === project.year
@@ -89,8 +91,12 @@ class ProjectListItem extends Component {
{/* Project Name */}
{group.id && {group.name}}
- {project.needHelp && !submissionsClosed && (
- looking for help
+ {userVote && userVote.length > 0 && userVote[0].awardCategory && (
+
+ You Voted{' '}
+ {awardCategoryOptions[userVote[0].awardCategory]?.name ||
+ userVote[0].awardCategory}
+
)}
@@ -155,6 +161,7 @@ class ProjectCardItem extends Component {
group: PropTypes.object,
submissionsClosed: PropTypes.bool,
isOlderYear: PropTypes.bool,
+ userVote: PropTypes.array,
};
render() {
@@ -166,6 +173,7 @@ class ProjectCardItem extends Component {
userList,
group,
isOlderYear,
+ userVote,
} = this.props;
const link =
@@ -202,8 +210,12 @@ class ProjectCardItem extends Component {
{group.id && {group.name}}
- {project.needHelp && !submissionsClosed && (
- looking for help
+ {userVote && userVote.length > 0 && userVote[0].awardCategory && (
+
+ You Voted{' '}
+ {awardCategoryOptions[userVote[0].awardCategory]?.name ||
+ userVote[0].awardCategory}
+
)}
@@ -291,6 +303,7 @@ class ProjectList extends Component {
groupFilter: null,
isWide: typeof window !== 'undefined' ? window.innerWidth >= 640 : true,
showIdeasTab: false, // Add this line to hide the Ideas tab
+ showMyStuffTab: false, // Add this line to hide the My Stuff tab
};
}
@@ -345,14 +358,16 @@ class ProjectList extends Component {
className={`Control-pill ${currentShow === 'projects' ? 'active' : ''}`}
to={{pathname, query: {...query, show: 'projects'}}}
>
- Projects {projectCount || 0}
-
-
- My Stuff {myProjectsCount || 0}
+ All Projects {projectCount || 0}
+ {this.state.showMyStuffTab && (
+
+ My Stuff {myProjectsCount || 0}
+
+ )}
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -477,6 +494,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -500,6 +518,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -517,6 +536,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -585,6 +605,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -602,6 +623,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -626,6 +648,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -643,6 +666,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -669,6 +693,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
@@ -686,6 +711,7 @@ class ProjectList extends Component {
v.project === project.key)}
firebase={firebase}
project={project}
awardCategoryOptions={awardCategoryOptions}
From 05a4401b1c42e70739785e6634164519effef089 Mon Sep 17 00:00:00 2001
From: John Manhart
Date: Sun, 24 Aug 2025 13:41:08 -0700
Subject: [PATCH 4/8] Adding in the new project slector tab styles
---
src/components/MicroCountdownTimer/index.js | 2 +-
src/components/PageHeader/index.js | 4 +-
src/components/header/index.js | 2 +-
src/components/header/styles.css | 4 +-
src/pages/ProjectList.css | 45 +++++++++++++++++++++
src/pages/ProjectList.js | 40 ++++++++++++++++++
6 files changed, 91 insertions(+), 6 deletions(-)
diff --git a/src/components/MicroCountdownTimer/index.js b/src/components/MicroCountdownTimer/index.js
index af70214..a1c816d 100644
--- a/src/components/MicroCountdownTimer/index.js
+++ b/src/components/MicroCountdownTimer/index.js
@@ -29,7 +29,7 @@ const MicroCountdownTimer = () => {
}, []);
if (timeLeft.days === 0) {
- return HACK NOW!!
;
+ return VOTE NOW!!
;
}
return {timeLeft.days} days away
;
diff --git a/src/components/PageHeader/index.js b/src/components/PageHeader/index.js
index 9abbefc..8a6604e 100644
--- a/src/components/PageHeader/index.js
+++ b/src/components/PageHeader/index.js
@@ -19,7 +19,7 @@ const PageHeader = ({
{title && {title}
}
{currentYear && {currentYear}
}
-
+ {/*
{showAddProjectButton && (
>
)}
-
+
*/}
);
diff --git a/src/components/header/index.js b/src/components/header/index.js
index 932b6d3..9449a2d 100644
--- a/src/components/header/index.js
+++ b/src/components/header/index.js
@@ -15,7 +15,7 @@ const Header = ({onLogin, onLogout, isAuthenticated, user, showMicroTimer = true
{this.state.isWide && (
@@ -466,6 +498,10 @@ class ProjectList extends Component {
myProjectsCount: myProjects.length,
myVotesCount: userVotes.length,
viewStyle,
+ westCoastCount: Math.floor(actualProjects.length * 0.3),
+ eastCoastCount: Math.floor(actualProjects.length * 0.4),
+ europeCount: Math.floor(actualProjects.length * 0.3),
+ allProjectsCount: actualProjects.length,
})}
{showIdeas && projectIdeas.length > 0 && (
@@ -842,6 +878,10 @@ class ProjectList extends Component {
myProjectsCount: myProjects.length,
myVotesCount: userVotes.length,
viewStyle,
+ westCoastCount: Math.floor((projectsLFH.length + otherProjects.length) * 0.3),
+ eastCoastCount: Math.floor((projectsLFH.length + otherProjects.length) * 0.4),
+ europeCount: Math.floor((projectsLFH.length + otherProjects.length) * 0.3),
+ allProjectsCount: projectsLFH.length + otherProjects.length,
})}
{emptyState}
From 7349797b47910250769d7399e7c19c0e40311296 Mon Sep 17 00:00:00 2001
From: John Manhart
Date: Sun, 24 Aug 2025 13:54:25 -0700
Subject: [PATCH 5/8] Adding in some final touches to the region bar
---
src/pages/ProjectList.css | 1 -
src/pages/ProjectList.js | 199 +++++++++++++++++++++++++++++++++++---
2 files changed, 187 insertions(+), 13 deletions(-)
diff --git a/src/pages/ProjectList.css b/src/pages/ProjectList.css
index 6fbe840..38e0fb4 100644
--- a/src/pages/ProjectList.css
+++ b/src/pages/ProjectList.css
@@ -388,7 +388,6 @@
background: var(--color-gray400);
border-radius: 10px;
padding: 2px;
- margin-left: 1rem;
}
.RegionToggle button {
appearance: none;
diff --git a/src/pages/ProjectList.js b/src/pages/ProjectList.js
index bca9f59..f062b5f 100644
--- a/src/pages/ProjectList.js
+++ b/src/pages/ProjectList.js
@@ -305,6 +305,13 @@ class ProjectList extends Component {
showIdeasTab: false, // Add this line to hide the Ideas tab
showMyStuffTab: false, // Add this line to hide the My Stuff tab
selectedRegion: 'all', // Default to All Projects
+ regionCounts: {
+ westCoast: 0,
+ eastCoast: 0,
+ europe: 0,
+ allProjects: 0,
+ myVotes: 0,
+ },
};
}
@@ -317,6 +324,80 @@ class ProjectList extends Component {
this._handleResize();
}
+ componentDidUpdate(prevProps) {
+ // Update region counts when projectList or groupsList changes
+ if (
+ prevProps.projectList !== this.props.projectList ||
+ prevProps.groupsList !== this.props.groupsList
+ ) {
+ this.calculateRegionCounts();
+ }
+
+ // Update myVotes count when year or auth changes
+ if (prevProps.year !== this.props.year || prevProps.auth !== this.props.auth) {
+ this.updateMyVotesCount();
+ }
+ }
+
+ calculateRegionCounts() {
+ const {projectList, groupsList} = this.props;
+ if (!projectList || !groupsList) return;
+
+ const projects = mapObject(projectList);
+ const westCoast = projects.filter((project) => {
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('west') ||
+ group.name.toLowerCase().includes('california') ||
+ group.name.toLowerCase().includes('seattle'))
+ );
+ }).length;
+
+ const eastCoast = projects.filter((project) => {
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('east') ||
+ group.name.toLowerCase().includes('new york') ||
+ group.name.toLowerCase().includes('boston'))
+ );
+ }).length;
+
+ const europe = projects.filter((project) => {
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('europe') ||
+ group.name.toLowerCase().includes('london') ||
+ group.name.toLowerCase().includes('berlin'))
+ );
+ }).length;
+
+ this.setState({
+ regionCounts: {
+ westCoast,
+ eastCoast,
+ europe,
+ allProjects: projects.length,
+ myVotes: 0, // This will be updated separately since it depends on user votes
+ },
+ });
+ }
+
+ updateMyVotesCount() {
+ const {year, auth} = this.props;
+ if (!year || !auth) return;
+
+ const userVotes = year ? getAuthUserVotes(auth.uid, year.votes) : [];
+ this.setState((prevState) => ({
+ regionCounts: {
+ ...prevState.regionCounts,
+ myVotes: userVotes.length,
+ },
+ }));
+ }
+
componentWillUnmount() {
if (this._handleResize) window.removeEventListener('resize', this._handleResize);
}
@@ -359,12 +440,12 @@ class ProjectList extends Component {
Ideas {ideaCount || 0}
)}
-
All Projects {projectCount || 0}
-
+ */}
{this.state.showMyStuffTab && (
{myProjectsCount || 0}
)}
-
My Votes {myVotesCount || 0}
-
+ */}
+
@@ -443,6 +531,48 @@ class ProjectList extends Component {
groupsList = {};
}
let projects = mapObject(projectList);
+
+ // Apply region filtering for closed years
+ if (this.state.selectedRegion !== 'all') {
+ if (this.state.selectedRegion === 'west') {
+ projects = projects.filter((project) => {
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('west') ||
+ group.name.toLowerCase().includes('california') ||
+ group.name.toLowerCase().includes('seattle'))
+ );
+ });
+ } else if (this.state.selectedRegion === 'east') {
+ projects = projects.filter((project) => {
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('east') ||
+ group.name.toLowerCase().includes('new york') ||
+ group.name.toLowerCase().includes('boston'))
+ );
+ });
+ } else if (this.state.selectedRegion === 'europe') {
+ projects = projects.filter((project) => {
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('europe') ||
+ group.name.toLowerCase().includes('london') ||
+ group.name.toLowerCase().includes('berlin'))
+ );
+ });
+ } else if (this.state.selectedRegion === 'my-votes') {
+ // Filter for projects the user has voted on
+ const userVotes = year ? getAuthUserVotes(auth.uid, year.votes) : [];
+ projects = projects.filter((project) =>
+ userVotes.some((vote) => vote.project === project.key)
+ );
+ }
+ }
+
let winningProjects = [];
let otherProjects = [];
@@ -498,10 +628,10 @@ class ProjectList extends Component {
myProjectsCount: myProjects.length,
myVotesCount: userVotes.length,
viewStyle,
- westCoastCount: Math.floor(actualProjects.length * 0.3),
- eastCoastCount: Math.floor(actualProjects.length * 0.4),
- europeCount: Math.floor(actualProjects.length * 0.3),
- allProjectsCount: actualProjects.length,
+ westCoastCount: this.state.regionCounts.westCoast,
+ eastCoastCount: this.state.regionCounts.eastCoast,
+ europeCount: this.state.regionCounts.europe,
+ allProjectsCount: this.state.regionCounts.allProjects,
})}
{showIdeas && projectIdeas.length > 0 && (
@@ -793,6 +923,51 @@ class ProjectList extends Component {
}
let projects = mapObject(projectList);
+
+ // Apply region filtering
+ if (this.state.selectedRegion !== 'all') {
+ if (this.state.selectedRegion === 'west') {
+ projects = projects.filter((project) => {
+ // Filter for West Coast projects - you can customize this logic
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('west') ||
+ group.name.toLowerCase().includes('california') ||
+ group.name.toLowerCase().includes('seattle'))
+ );
+ });
+ } else if (this.state.selectedRegion === 'east') {
+ projects = projects.filter((project) => {
+ // Filter for East Coast projects
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('east') ||
+ group.name.toLowerCase().includes('new york') ||
+ group.name.toLowerCase().includes('boston'))
+ );
+ });
+ } else if (this.state.selectedRegion === 'europe') {
+ projects = projects.filter((project) => {
+ // Filter for Europe projects
+ const group = groupsList[project.group];
+ return (
+ group &&
+ (group.name.toLowerCase().includes('europe') ||
+ group.name.toLowerCase().includes('london') ||
+ group.name.toLowerCase().includes('berlin'))
+ );
+ });
+ } else if (this.state.selectedRegion === 'my-votes') {
+ // Filter for projects the user has voted on
+ const userVotes = year ? getAuthUserVotes(auth.uid, year.votes) : [];
+ projects = projects.filter((project) =>
+ userVotes.some((vote) => vote.project === project.key)
+ );
+ }
+ }
+
if (this.state.groupFilter) {
if (this.state.groupFilter.value === '') {
projects = projects.filter((project) => !project.group);
@@ -878,10 +1053,10 @@ class ProjectList extends Component {
myProjectsCount: myProjects.length,
myVotesCount: userVotes.length,
viewStyle,
- westCoastCount: Math.floor((projectsLFH.length + otherProjects.length) * 0.3),
- eastCoastCount: Math.floor((projectsLFH.length + otherProjects.length) * 0.4),
- europeCount: Math.floor((projectsLFH.length + otherProjects.length) * 0.3),
- allProjectsCount: projectsLFH.length + otherProjects.length,
+ westCoastCount: this.state.regionCounts.westCoast,
+ eastCoastCount: this.state.regionCounts.eastCoast,
+ europeCount: this.state.regionCounts.europe,
+ allProjectsCount: this.state.regionCounts.allProjects,
})}
{emptyState}
From b7834eb6dba82082060914f33d683fa6d991c3c3 Mon Sep 17 00:00:00 2001
From: John Manhart
Date: Sun, 24 Aug 2025 14:10:06 -0700
Subject: [PATCH 6/8] adding in a fix so past years work with the new region
selector
---
src/pages/ProjectList.js | 109 +++++++++++++++++++++++++++------------
1 file changed, 76 insertions(+), 33 deletions(-)
diff --git a/src/pages/ProjectList.js b/src/pages/ProjectList.js
index f062b5f..18a3e5a 100644
--- a/src/pages/ProjectList.js
+++ b/src/pages/ProjectList.js
@@ -337,6 +337,14 @@ class ProjectList extends Component {
if (prevProps.year !== this.props.year || prevProps.auth !== this.props.auth) {
this.updateMyVotesCount();
}
+
+ // Reset region selection if region toggle is hidden
+ if (
+ prevProps.groupsList !== this.props.groupsList &&
+ !this.shouldShowRegionToggle()
+ ) {
+ this.setState({selectedRegion: 'all'});
+ }
}
calculateRegionCounts() {
@@ -398,6 +406,32 @@ class ProjectList extends Component {
}));
}
+ shouldShowRegionToggle() {
+ const {groupsList} = this.props;
+ if (!groupsList) return false;
+
+ // Check if there are any groups defined for this year
+ const hasGroups = Object.keys(groupsList).length > 0;
+
+ // Check if any groups have region-related names
+ const hasRegionGroups = Object.values(groupsList).some(
+ (group) =>
+ group &&
+ group.name &&
+ (group.name.toLowerCase().includes('west') ||
+ group.name.toLowerCase().includes('east') ||
+ group.name.toLowerCase().includes('europe') ||
+ group.name.toLowerCase().includes('california') ||
+ group.name.toLowerCase().includes('seattle') ||
+ group.name.toLowerCase().includes('new york') ||
+ group.name.toLowerCase().includes('boston') ||
+ group.name.toLowerCase().includes('london') ||
+ group.name.toLowerCase().includes('berlin'))
+ );
+
+ return hasGroups && hasRegionGroups;
+ }
+
componentWillUnmount() {
if (this._handleResize) window.removeEventListener('resize', this._handleResize);
}
@@ -461,39 +495,47 @@ class ProjectList extends Component {
My Votes {myVotesCount || 0}
*/}
-
-
-
-
-
-
-
+ {this.shouldShowRegionToggle() ? (
+
+
+
+
+
+
+
+ ) : (
+
+
+
+ )}