Skip to content

Commit

Permalink
Add team page hero and about
Browse files Browse the repository at this point in the history
  • Loading branch information
cchrischen committed May 2, 2024
1 parent 18c6257 commit 0adb944
Show file tree
Hide file tree
Showing 5 changed files with 497 additions and 3 deletions.
10 changes: 10 additions & 0 deletions new-dti-website/components/blob.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const RedBlob: React.FC<{ className: string; intensity: number }> = ({ className, intensity }) => (
<div
className={`absolute h-[600px] w-[600px] rounded-full overflow-hidden z-0 ${className}`}
style={{
backgroundImage: `radial-gradient(rgba(192, 12, 12, ${intensity}) 5%, transparent 75%)`
}}
/>
);

export default RedBlob;
260 changes: 260 additions & 0 deletions new-dti-website/components/team/TeamAbout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
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';
import useScreenSize from '../../src/hooks/useScreenSize';
import RedBlob from '../blob';

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: IdolMember[];
};

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 { width } = useScreenSize();

const allMembers = FA23Members.members as IdolMember[];

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: IdolMember) => {
const fullRoleName =
member.role === 'tpm' || member.role === 'dev-advisor' ? 'developer' : member.role;
roleStats[fullRoleName].people += 1;
if (member.major) roleStats[fullRoleName].majors.add(member.major.trim());
if (member.doubleMajor) roleStats[fullRoleName].majors.add(member.doubleMajor.trim());
});

return (
<div className="flex md:flex-row xs:flex-col items-center justify-between lg:ml-6 relative z-10">
<div className="flex">
<div className="flex md:flex-col xs:flex-row lg:gap-y-10 md:gap-y-[30px]">
<div className="text-center md:pl-10 xs:w-1/3 md:border-l-red-600 md:border-2 border-transparent">
<h1 className="font-semibold lg:text-[52px] md:text-[40px] xs:text-[32px]">
{chartSection ? roleStats[chartSection].people : allMembers.length}
</h1>
<p className="lg:text-[22px] md:text-lg text-[#E4E4E4] xs:text-sm">Members</p>
</div>
<div className="text-center md:pl-10 xs:w-1/3 border-l-red-600 border-2 border-transparent">
<h1 className="font-semibold lg:text-[52px] md:text-[40px] xs:text-[32px]">
{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="lg:text-[22px] md:text-lg text-[#E4E4E4] xs:text-sm">Different majors</p>
</div>
<div className="text-center md:pl-10 xs:w-1/3 border-l-red-600 border-2 border-transparent">
<h1 className="font-semibold lg:text-[52px] md:text-[40px] xs:text-[32px]">7</h1>
<p className="lg:text-[22px] md:text-lg text-[#E4E4E4] xs:text-sm">
Represented colleges
</p>
</div>
</div>
</div>
<div>
<PieChart
width={width >= 1024 ? 400 : 300}
height={width >= 1024 ? 400 : 300}
chartSection={chartSection}
setChartSection={setChartSection}
allMembers={allMembers}
roleStats={roleStats}
/>
</div>
<div className="grid md:grid-cols-1 xs:grid-cols-2 md:gap-8 xs:gap-2 md:ml-5 lg:ml-10">
{Object.keys(roleStats).map((role) => {
if (role === 'tpm' || role === 'dev-advisor') return <></>;
return (
<div
key={role}
className="flex lg:gap-7 xs:gap-4 md:gap-[25px] items-center"
onMouseEnter={() => setChartSection(role)}
onMouseLeave={() => setChartSection(undefined)}
>
<div
className={`min-w-10 rounded-xl border-[6px] border-[${roleStats[role].color}]`}
style={{ borderColor: roleStats[role].color, minWidth: width >= 728 ? 40 : 24}}
/>
<p
className={`lg:text-[22px] md:text-lg font-bold ${
chartSection === role ? 'text-white' : 'text-[#877B7B]'
}`}
>
{roleStats[role].name}
</p>
</div>
);
})}
</div>
</div>
);
};

const TeamAbout = () => (
<div className="relative flex justify-center text-white bg-black overflow-hidden">
<RedBlob intensity={0.6} className="left-[-200px] top-[200px]" />
<div
className="flex flex-col gap-12 xs:mx-4 xs:my-[60px] md:mx-10 md:my-24
lg:m-[70px_100px] xl:m-[115px_240px] 2xl:my-[115px] max-w-5xl relative z-10"
>
<div className="flex flex-col items-center xs:gap-[30px_0px]">
<div className="flex md:flex-row xs:flex-col justify-between gap-[30px] items-center">
<div className="flex flex-col md:w-1/2 gap-6">
<h1 className="font-semibold text-[32px]">We are Cornell DTI</h1>
<p className="md:text-lg xs:text-sm">
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="text-left mb-3">@2022</p>
<Image
src="/images/full-team.png"
alt="2022 DTI Team"
width={490}
height={370}
className="rounded-[23px] lg:w-[490px] md:w-[383px] xs:w-[350px] h-auto"
/>
</div>
</div>
<div className={`${ibm_plex_mono.className} text-sm relative w-fit xl:bottom-[84px]`}>
<p className="mb-3 text-sm">@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] xs:w-[350px] h-auto"
/>
</div>
</div>
<RedBlob intensity={0.7} className="right-[-500px] top-[600px]" />
<div className="lg:w-2/3 md:w-full mt-[63px] relative z-10">
<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 />
<RedBlob intensity={0.6} className="bottom-[-100px] left-[-400px]" />
</div>
</div>
);
export default TeamAbout;
Loading

0 comments on commit 0adb944

Please sign in to comment.