|
|
|
@ -9,7 +9,11 @@ import { Link } from "@/components/Link"; |
|
|
|
|
import { TeamMember } from "@/components/TeamMember"; |
|
|
|
|
import { TeamMemberCard } from "@/components/TeamMemberCard"; |
|
|
|
|
import { Title } from "@/components/Title"; |
|
|
|
|
import { getExecs, Metadata, getMemberImagePath } from "@/lib/team"; |
|
|
|
|
import { |
|
|
|
|
getExecs, |
|
|
|
|
Metadata as TeamMemberData, |
|
|
|
|
getMemberImagePath, |
|
|
|
|
} from "@/lib/team"; |
|
|
|
|
import { getCurrentTermYear } from "@/utils"; |
|
|
|
|
|
|
|
|
|
import designData from "../../content/team/design-team.json"; |
|
|
|
@ -27,88 +31,21 @@ import styles from "./team.module.css"; |
|
|
|
|
|
|
|
|
|
interface SerializedExec { |
|
|
|
|
content: MDXRemoteSerializeResult; |
|
|
|
|
metadata: Metadata; |
|
|
|
|
metadata: TeamMemberData; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
interface Team { |
|
|
|
|
id: string; |
|
|
|
|
name: string; |
|
|
|
|
members: TeamMemberData[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
interface Props { |
|
|
|
|
execs: SerializedExec[]; |
|
|
|
|
design: Metadata[]; |
|
|
|
|
discord: Metadata[]; |
|
|
|
|
events: Metadata[]; |
|
|
|
|
external: Metadata[]; |
|
|
|
|
marketing: Metadata[]; |
|
|
|
|
photography: Metadata[]; |
|
|
|
|
representatives: Metadata[]; |
|
|
|
|
website: Metadata[]; |
|
|
|
|
systems: Metadata[]; |
|
|
|
|
terminal: Metadata[]; |
|
|
|
|
teams: Team[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export default function Team({ |
|
|
|
|
execs, |
|
|
|
|
design, |
|
|
|
|
discord, |
|
|
|
|
events, |
|
|
|
|
external, |
|
|
|
|
marketing, |
|
|
|
|
photography, |
|
|
|
|
representatives, |
|
|
|
|
website, |
|
|
|
|
systems, |
|
|
|
|
terminal, |
|
|
|
|
}: Props) { |
|
|
|
|
const teams = [ |
|
|
|
|
{ |
|
|
|
|
id: "reps", |
|
|
|
|
name: "Community Representatives", |
|
|
|
|
members: representatives, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "design", |
|
|
|
|
name: "Design Team", |
|
|
|
|
members: design, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "discord", |
|
|
|
|
name: "Discord Team", |
|
|
|
|
members: discord, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "events", |
|
|
|
|
name: "Events Team", |
|
|
|
|
members: events, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "external", |
|
|
|
|
name: "External Affairs Team", |
|
|
|
|
members: external, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "marketing", |
|
|
|
|
name: "Marketing Team", |
|
|
|
|
members: marketing, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "photography", |
|
|
|
|
name: "Photography Team", |
|
|
|
|
members: photography, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "website", |
|
|
|
|
name: "Web Committee", |
|
|
|
|
members: website, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "system", |
|
|
|
|
name: "Systems Committee", |
|
|
|
|
members: systems, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "terminal", |
|
|
|
|
name: "Terminal Committee", |
|
|
|
|
members: terminal, |
|
|
|
|
}, |
|
|
|
|
]; |
|
|
|
|
export default function Team({ execs, teams }: Props) { |
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<Title>Team</Title> |
|
|
|
@ -118,16 +55,11 @@ export default function Team({ |
|
|
|
|
<h1 className={styles.header}>Meet the Team!</h1> |
|
|
|
|
<div className={styles.nav}> |
|
|
|
|
<Link href="#execs">The Executives</Link> |
|
|
|
|
<Link href="#reps">Community Representatives</Link> |
|
|
|
|
<Link href="#design">Design</Link> |
|
|
|
|
<Link href="#discord">Discord</Link> |
|
|
|
|
<Link href="#events">Events</Link> |
|
|
|
|
<Link href="#external">External Affairs</Link> |
|
|
|
|
<Link href="#marketing">Marketing</Link> |
|
|
|
|
<Link href="#photography">Photography</Link> |
|
|
|
|
<Link href="#website">Web Committee</Link> |
|
|
|
|
<Link href="#system">Systems Committee</Link> |
|
|
|
|
<Link href="#terminal">Terminal Committee</Link> |
|
|
|
|
{teams.map((team) => ( |
|
|
|
|
<Link href={`#${team.id}`} key={team.id}> |
|
|
|
|
{team.name} |
|
|
|
|
</Link> |
|
|
|
|
))} |
|
|
|
|
</div> |
|
|
|
|
<h2 |
|
|
|
|
className={styles.subheading} |
|
|
|
@ -176,7 +108,7 @@ Team.Layout = function TeamLayout(props: { children: React.ReactNode }) { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
interface MembersProps { |
|
|
|
|
team: Metadata[]; |
|
|
|
|
team: TeamMemberData[]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function MembersList(props: MembersProps) { |
|
|
|
@ -189,87 +121,104 @@ function MembersList(props: MembersProps) { |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type TeamMember = Omit<Metadata, "image"> & { image?: string }; |
|
|
|
|
|
|
|
|
|
async function getTeamWithImages(team: TeamMember[]) { |
|
|
|
|
return await Promise.all( |
|
|
|
|
team.map(async (member) => { |
|
|
|
|
const image = member.image ?? (await getMemberImagePath(member.name)); |
|
|
|
|
return { |
|
|
|
|
...member, |
|
|
|
|
image, |
|
|
|
|
}; |
|
|
|
|
}) |
|
|
|
|
); |
|
|
|
|
async function getTeamWithImages(team: Team): Promise<Team> { |
|
|
|
|
return { |
|
|
|
|
...team, |
|
|
|
|
members: await Promise.all( |
|
|
|
|
team.members.map(async (member) => { |
|
|
|
|
const image = member.image ?? (await getMemberImagePath(member.name)); |
|
|
|
|
return { |
|
|
|
|
...member, |
|
|
|
|
image, |
|
|
|
|
}; |
|
|
|
|
}) |
|
|
|
|
), |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function memberComparer(a: Metadata, b: Metadata) { |
|
|
|
|
function memberComparer(a: TeamMemberData, b: TeamMemberData) { |
|
|
|
|
return a.name.localeCompare(b.name); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function sortTeam(team: Metadata[]): Metadata[] { |
|
|
|
|
const leads = team |
|
|
|
|
function sortTeamMembers(team: Team): Team { |
|
|
|
|
const leads = team.members |
|
|
|
|
.filter(({ role }) => role === "Team Lead") |
|
|
|
|
.sort(memberComparer); |
|
|
|
|
const general = team.filter(({ role }) => !role).sort(memberComparer); |
|
|
|
|
const others = team |
|
|
|
|
|
|
|
|
|
const general = team.members.filter(({ role }) => !role).sort(memberComparer); |
|
|
|
|
|
|
|
|
|
const others = team.members |
|
|
|
|
.filter(({ role }) => !!role && role !== "Team Lead") |
|
|
|
|
.sort(memberComparer); |
|
|
|
|
|
|
|
|
|
return [...leads, ...general, ...others]; |
|
|
|
|
return { ...team, members: [...leads, ...general, ...others] }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export const getStaticProps: GetStaticProps<Props> = async () => { |
|
|
|
|
const execs = await getExecs(getCurrentTermYear()); |
|
|
|
|
|
|
|
|
|
let [ |
|
|
|
|
design, |
|
|
|
|
discord, |
|
|
|
|
events, |
|
|
|
|
external, |
|
|
|
|
marketing, |
|
|
|
|
photography, |
|
|
|
|
representatives, |
|
|
|
|
website, |
|
|
|
|
systems, |
|
|
|
|
terminal, |
|
|
|
|
] = await Promise.all([ |
|
|
|
|
getTeamWithImages(designData), |
|
|
|
|
getTeamWithImages(discordData), |
|
|
|
|
getTeamWithImages(eventsData), |
|
|
|
|
getTeamWithImages(externalData), |
|
|
|
|
getTeamWithImages(marketingData), |
|
|
|
|
getTeamWithImages(photographyData), |
|
|
|
|
getTeamWithImages(repsData), |
|
|
|
|
getTeamWithImages(webData), |
|
|
|
|
getTeamWithImages(systemsData), |
|
|
|
|
getTeamWithImages(terminalData), |
|
|
|
|
]); |
|
|
|
|
// Note that rawTeams do not contain image paths of members, even though
|
|
|
|
|
// TypeScript thinks that it does. It's just to simplify some code.
|
|
|
|
|
const rawTeams = [ |
|
|
|
|
{ |
|
|
|
|
id: "reps", |
|
|
|
|
name: "Community Representatives", |
|
|
|
|
members: repsData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "design", |
|
|
|
|
name: "Design", |
|
|
|
|
members: designData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "discord", |
|
|
|
|
name: "Discord", |
|
|
|
|
members: discordData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "events", |
|
|
|
|
name: "Events", |
|
|
|
|
members: eventsData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "external", |
|
|
|
|
name: "External Affairs", |
|
|
|
|
members: externalData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "marketing", |
|
|
|
|
name: "Marketing", |
|
|
|
|
members: marketingData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "photography", |
|
|
|
|
name: "Photography", |
|
|
|
|
members: photographyData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "website", |
|
|
|
|
name: "Web Committee", |
|
|
|
|
members: webData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "system", |
|
|
|
|
name: "Systems Committee", |
|
|
|
|
members: systemsData, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
id: "terminal", |
|
|
|
|
name: "Terminal Committee", |
|
|
|
|
members: terminalData, |
|
|
|
|
}, |
|
|
|
|
] as Team[]; |
|
|
|
|
|
|
|
|
|
design = sortTeam(design); |
|
|
|
|
discord = sortTeam(discord); |
|
|
|
|
events = sortTeam(events); |
|
|
|
|
external = sortTeam(external); |
|
|
|
|
marketing = sortTeam(marketing); |
|
|
|
|
representatives = sortTeam(representatives); |
|
|
|
|
photography = sortTeam(photography); |
|
|
|
|
website = sortTeam(website); |
|
|
|
|
systems = sortTeam(systems); |
|
|
|
|
terminal = sortTeam(terminal); |
|
|
|
|
const teamsWithImages = await Promise.all(rawTeams.map(getTeamWithImages)); |
|
|
|
|
const teamsAfterSorting = teamsWithImages.map(sortTeamMembers); |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
props: { |
|
|
|
|
execs, |
|
|
|
|
design, |
|
|
|
|
discord, |
|
|
|
|
events, |
|
|
|
|
external, |
|
|
|
|
marketing, |
|
|
|
|
photography, |
|
|
|
|
representatives, |
|
|
|
|
website, |
|
|
|
|
systems, |
|
|
|
|
terminal, |
|
|
|
|
teams: teamsAfterSorting, |
|
|
|
|
}, |
|
|
|
|
}; |
|
|
|
|
}; |
|
|
|
|