-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d72ed53
commit 70adb73
Showing
1 changed file
with
244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
import { Dispatch, SetStateAction, useState } from 'react'; | ||
import Image from 'next/image'; | ||
import { ibm_plex_mono } from '../../src/app/layout'; | ||
import FA23Members from '../../../backend/src/members-archive/fa23.json'; | ||
|
||
type roleStatistics = { | ||
[key: string]: { | ||
name: string; | ||
color: string; | ||
people: number; | ||
majors: Set<string>; | ||
colleges: Set<string>; | ||
}; | ||
}; | ||
|
||
type PieChartProps = { | ||
width: number; | ||
height: number; | ||
chartSection: string | undefined; | ||
setChartSection: Dispatch<SetStateAction<string | undefined>>; | ||
roleStats: roleStatistics; | ||
allMembers: WebsiteMember[]; | ||
}; | ||
|
||
const PieChart: React.FC<PieChartProps> = ({ | ||
width, | ||
height, | ||
chartSection, | ||
setChartSection, | ||
roleStats, | ||
allMembers | ||
}) => { | ||
const radius = 175; | ||
const hoverRadius = 190; | ||
let previousPoint = [0, -radius]; | ||
let totalAngle = 0; | ||
|
||
const polarToRect = (angle: number, radius: number) => { | ||
const newX = -radius * Math.cos(angle + Math.PI / 2); | ||
const newY = -radius * Math.sin(angle + Math.PI / 2); | ||
return [newX, newY]; | ||
}; | ||
|
||
const pointAsString = (point: number[]) => point.join(' '); | ||
const scale = (point: number[], scalar: number) => point.map((x) => scalar * x); | ||
|
||
return ( | ||
<svg height={height} width={width} viewBox="-200 -200 400 400"> | ||
{Object.keys(roleStats).map((role) => { | ||
const percentage = roleStats[role].people / allMembers.length; | ||
const theta = 2 * Math.PI * percentage; | ||
|
||
const arcPoint1 = | ||
role === chartSection ? scale(previousPoint, hoverRadius / radius) : previousPoint; | ||
const currentRadius = role === chartSection ? hoverRadius : radius; | ||
|
||
totalAngle += theta; | ||
const arcPoint2 = polarToRect(totalAngle, role === chartSection ? hoverRadius : radius); | ||
|
||
const nextPoint = polarToRect(totalAngle, radius); | ||
const textLocation = polarToRect((2 * totalAngle - theta) / 2, (3 * radius) / 4); | ||
previousPoint = nextPoint; | ||
|
||
return ( | ||
<g | ||
key={role} | ||
onMouseEnter={() => setChartSection(role)} | ||
onMouseLeave={() => setChartSection(undefined)} | ||
> | ||
<path | ||
d={`M 0 0 L ${pointAsString(arcPoint1)} A ${currentRadius} ${currentRadius} 0 ${ | ||
theta > Math.PI ? `1` : `0` | ||
} 1 ${pointAsString(arcPoint2)} L 0 0`} | ||
fill={roleStats[role].color} | ||
/> | ||
<text | ||
x={textLocation[0]} | ||
y={textLocation[1]} | ||
className={`font-bold text-lg ${ | ||
role === 'developer' || role === 'lead' ? 'fill-white' : 'fill-black' | ||
}`} | ||
style={{ textAnchor: 'middle' }} | ||
> | ||
{`${Math.round(percentage * 100)}%`} | ||
</text> | ||
</g> | ||
); | ||
})} | ||
</svg> | ||
); | ||
}; | ||
|
||
const TeamStatistics = () => { | ||
const [chartSection, setChartSection] = useState<string | undefined>(undefined); | ||
|
||
const allMembers = FA23Members.members; | ||
|
||
const roleStats: roleStatistics = { | ||
designer: { | ||
name: 'Design', | ||
color: '#FFBCBC', | ||
people: 0, | ||
majors: new Set(), | ||
colleges: new Set() | ||
}, | ||
developer: { | ||
name: 'Development', | ||
color: '#D63D3D', | ||
people: 0, | ||
majors: new Set(), | ||
colleges: new Set() | ||
}, | ||
pm: { name: 'Product', color: '#FFFFFF', people: 0, majors: new Set(), colleges: new Set() }, | ||
business: { | ||
name: 'Business', | ||
color: '#B7B7B7', | ||
people: 0, | ||
majors: new Set(), | ||
colleges: new Set() | ||
}, | ||
lead: { name: 'Leads', color: '#484848', people: 0, majors: new Set(), colleges: new Set() } | ||
}; | ||
|
||
allMembers.forEach((member: WebsiteMember) => { | ||
const fullRoleName = member.role === 'tpm' ? 'developer' : member.role; | ||
roleStats[fullRoleName].people += 1; | ||
if (member.major) roleStats[fullRoleName].majors.add(member.major); | ||
if (member.doubleMajor) roleStats[fullRoleName].majors.add(member.doubleMajor); | ||
}); | ||
|
||
return ( | ||
<div className="flex items-center justify-between lg:ml-6"> | ||
<div className="flex"> | ||
<div className="flex flex-col gap-y-10"> | ||
<div className="pl-10 border-l-red-600 border-2 border-y-black border-r-black"> | ||
<h1 className="font-semibold text-[52px]"> | ||
{chartSection ? roleStats[chartSection].people : allMembers.length} | ||
</h1> | ||
<p className="text-[22px] text-[#E4E4E4]">Members</p> | ||
</div> | ||
<div className="pl-10 border-l-red-600 border-2 border-y-black border-r-black"> | ||
<h1 className="font-semibold text-[52px]"> | ||
{chartSection | ||
? roleStats[chartSection].majors.size | ||
: allMembers.reduce((acc, val) => { | ||
if (val.major) acc.add(val.major); | ||
if (val.doubleMajor) acc.add(val.doubleMajor); | ||
return acc; | ||
}, new Set()).size} | ||
</h1> | ||
<p className="text-[22px] text-[#E4E4E4]">Different majors</p> | ||
</div> | ||
<div className="pl-10 border-l-red-600 border-2 border-y-black border-r-black"> | ||
<h1 className="font-semibold text-[52px]">7</h1> | ||
<p className="text-[22px] text-[#E4E4E4] w-max">Represented colleges</p> | ||
</div> | ||
</div> | ||
</div> | ||
<div> | ||
<PieChart | ||
width={400} | ||
height={400} | ||
chartSection={chartSection} | ||
setChartSection={setChartSection} | ||
allMembers={allMembers} | ||
roleStats={roleStats} | ||
/> | ||
</div> | ||
<div className="flex flex-col gap-8 md:ml-5 lg:ml-10"> | ||
{Object.keys(roleStats).map((role) => ( | ||
<div | ||
className="flex gap-7 items-center" | ||
onMouseEnter={() => setChartSection(role)} | ||
onMouseLeave={() => setChartSection(undefined)} | ||
> | ||
<div | ||
className={`w-11 h-min rounded-xl border-[6px] border-[${roleStats[role].color}]`} | ||
style={{ borderColor: roleStats[role].color }} | ||
/> | ||
<p | ||
className={`text-[22px] font-bold ${ | ||
chartSection === role ? 'text-white' : 'text-[#877B7B]' | ||
}`} | ||
> | ||
{roleStats[role].name} | ||
</p> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
const TeamAbout = () => ( | ||
<div className="flex justify-center text-white bg-black "> | ||
<div className="flex flex-col gap-12 md:mx-10 md:my-24 lg:m-[70px_100px] xl:m-[115px_240px]"> | ||
<div className="flex flex-col items-center"> | ||
<div className="flex justify-between gap-[30px]"> | ||
<div className="flex flex-col w-1/2 mt-10 gap-6"> | ||
<h1 className="font-semibold text-[32px]">We are Cornell DTI</h1> | ||
<p className="text-lg"> | ||
Founded in 2017, DTI is a project team of{' '} | ||
<span className="font-bold"> | ||
80+ designers, developers, product managers, and business members | ||
</span>{' '} | ||
passionate about making change on campus and beyond. | ||
</p> | ||
</div> | ||
<div className={`${ibm_plex_mono.className} text-sm`}> | ||
<p className="mb-3">@2022</p> | ||
<Image | ||
src="/images/dti.png" | ||
alt="2022 DTI Team" | ||
width={490} | ||
height={370} | ||
className="rounded-[23px] lg:w-[490px] md:w-[383px] h-auto" | ||
/> | ||
</div> | ||
</div> | ||
<div className={`${ibm_plex_mono.className} text-sm relative w-fit xl:bottom-[84px]`}> | ||
<p className="mb-3">@2017</p> | ||
<Image | ||
src="/images/dti_2017.png" | ||
alt="2022 DTI Team" | ||
width={453} | ||
height={305} | ||
className="rounded-[23px] lg:w-[490px] md:w-[383px] h-auto" | ||
/> | ||
</div> | ||
</div> | ||
<div className="lg:w-2/3 md:w-full mt-[63px]"> | ||
<h1 className="font-semibold mb-4 text-[32px]">Who we are</h1> | ||
<p className="text-lg leading-6"> | ||
More than just being inclusive, our team strives to{' '} | ||
<span className="font-bold">bring many backgrounds and perspectives together</span> to | ||
solve community problems. These statistics come from recruiting across campus and seeking | ||
applicants with the best skills and potential for growth on the team. Updated Fall 2023. | ||
</p> | ||
</div> | ||
<TeamStatistics /> | ||
</div> | ||
</div> | ||
); | ||
export default TeamAbout; |