Merge branch 'main' into feat/organized-content

merge-requests/12/head
William Tran 2 years ago
commit 6099a0b337
  1. 2
      .gitignore
  2. 3
      .vscode/extensions.json
  3. 1
      .vscode/settings.json
  4. 47
      components/EventCard.module.css
  5. 48
      components/EventCard.tsx
  6. 63
      components/EventDescriptionCard.module.css
  7. 86
      components/EventDescriptionCard.tsx
  8. 27
      components/EventSetting.tsx
  9. 16
      components/Image.tsx
  10. 15
      components/MiniEventCard.module.css
  11. 19
      components/MiniEventCard.tsx
  12. 151
      components/Navbar.module.css
  13. 120
      components/Navbar.tsx
  14. 32
      components/NewsCard.module.css
  15. 30
      components/NewsCard.tsx
  16. 28
      components/TeamMember.module.css
  17. 29
      components/TeamMember.tsx
  18. 112
      components/TeamMemberCard.module.css
  19. 27
      components/TeamMemberCard.tsx
  20. 94
      components/playground.module.css
  21. 148
      components/playground.tsx
  22. 4
      content/playground/after-hours.event.mdx
  23. 14
      content/playground/alt-tab.event.mdx
  24. 9
      content/playground/codey.team-member.mdx
  25. 5
      content/playground/doge.team-member.mdx
  26. 17
      content/playground/ootb-react.event.mdx
  27. 14
      content/playground/unavailable.news.mdx
  28. 48
      next-env.d.ts
  29. 12
      next.config.js
  30. 11835
      package-lock.json
  31. 4
      package.json
  32. 27
      pages/_app.css
  33. 2
      pages/_app.tsx
  34. 1
      pages/about/code-of-conduct.mdx
  35. 1
      pages/about/constitution.mdx
  36. 1
      pages/about/index.mdx
  37. 1
      pages/about/team.mdx
  38. 1
      pages/events.mdx
  39. 1
      pages/get-involved.mdx
  40. 2
      pages/index.mdx
  41. 3
      pages/index.module.css
  42. 64
      pages/playground.mdx
  43. 1
      pages/resources.mdx
  44. 18
      postcss.config.json
  45. BIN
      public/images/logo-icon.png
  46. BIN
      public/images/playground/alt-tab.jpg
  47. BIN
      public/images/playground/codeyHi.png
  48. BIN
      public/images/playground/doge.jpg
  49. BIN
      public/images/playground/intro-ootb.jpg
  50. BIN
      public/images/profile.jpg
  51. 3
      public/images/team-member-placeholder.svg
  52. BIN
      public/logos/Discord.png
  53. BIN
      public/logos/Facebook.png
  54. BIN
      public/logos/Instagram.png
  55. BIN
      public/logos/Twitch.png

2
.gitignore vendored

@ -22,4 +22,4 @@
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
yarn-error.log*

@ -2,7 +2,6 @@
"recommendations": [
"dbaeumer.vscode-eslint",
"humao.rest-client",
"silvenon.mdx",
"xyc.vscode-mdx-preview"
"silvenon.mdx"
]
}

@ -38,4 +38,5 @@
"files.exclude": {
"node_modules": true
},
"editor.tabSize": 2
}

@ -0,0 +1,47 @@
.card {
display: flex;
flex-direction: row;
max-width: calc(1000rem / 16);
box-sizing: border-box;
padding: calc(24rem / 16);
}
.card aside {
flex: 0 0 calc(144rem / 16);
margin-right: calc(24rem / 16);
}
.card aside img {
width: 100%;
margin-bottom: 1rem;
}
.spacer {
margin-top: calc(76rem / 16);
}
.registerButton {
width: 100%;
}
.content > h1 {
font-size: calc(24rem / 16);
font-weight: 700;
font-style: normal;
margin-top: 0;
margin-bottom: 0;
}
.content,
.content > h2 {
color: var(--purple-2);
font-weight: 400;
font-style: normal;
margin-top: 0;
margin-bottom: 0;
}
.content > h2 {
font-size: 1rem;
margin-bottom: calc(14rem / 16);
}

@ -0,0 +1,48 @@
import React, { ReactNode } from "react";
import styles from "./EventCard.module.css";
import { EventSetting } from "./EventSetting";
import { Image } from "./Image";
interface EventCardProps {
name: string;
short: string;
date: Date;
online: boolean;
location: string;
poster?: string;
registerLink?: string;
children: ReactNode;
}
export function EventCard({
name,
date,
online,
location,
poster,
registerLink,
children,
}: EventCardProps) {
return (
<article className={styles.card}>
<aside>
{poster && <Image alt={name} src={poster} />}
{!poster && <div className={styles.spacer}></div>}
{/* TODO: use the <Button /> component */}
{registerLink && (
<button className={styles.registerButton}>
<a href={registerLink}>Register</a>
</button>
)}
</aside>
<section className={styles.content}>
<h1>{name}</h1>
<h2>
<EventSetting date={date} online={online} location={location} />
</h2>
<div>{children}</div>
</section>
</article>
);
}

@ -0,0 +1,63 @@
.card {
display: flex;
box-sizing: border-box;
max-width: calc(540rem / 16);
padding: calc(24rem / 16);
border-radius: calc(4rem / 16);
background-color: white;
}
.poster {
width: calc(150rem / 16);
height: calc(150rem / 16);
margin-right: calc(20rem / 16);
}
.details {
position: relative;
width: 100%;
}
.name {
color: var(--purple-2);
font-weight: bolder;
font-size: calc(18rem / 16);
line-height: calc(27rem / 16);
margin: 0;
}
.desc {
color: var(--purple-2);
margin-top: calc(12rem / 16);
}
.spacer {
height: calc(35rem / 16);
}
.button {
position: absolute;
bottom: 0;
left: 0;
}
.logo {
width: calc(30rem / 16);
position: absolute;
bottom: 0;
right: 0;
}
.setting {
margin: 0;
color: var(--blue-1);
font-weight: bolder;
font-size: calc(14rem / 16);
}
@media only screen and (max-width: calc(768rem / 16)) {
.card {
padding: 0;
background-color: #e1eefa;
}
}

@ -0,0 +1,86 @@
import React, { ReactNode } from "react";
// import { Button } from "./Button";
import { Image } from "./Image";
import { EventSetting } from "./EventSetting";
import styles from "./EventDescriptionCard.module.css";
interface Props {
name: string;
online: boolean;
location: string;
date: Date;
poster?: string;
registerLink?: string;
children: ReactNode;
}
function getPlatformURL(platform: string) {
switch (platform) {
case "Twitch":
return "https://www.twitch.tv/uwcsclub";
case "Discord":
return "https://discord.gg/pHfYBCg";
case "Facebook":
return "https://www.facebook.com/uw.computerscienceclub";
case "Instagram":
return "https://www.instagram.com/uwcsclub/";
default:
return;
}
}
/**
* @remarks
* - Child elements will display as the event's description
* - Assuming date prop is in EST
* - poster is the event's image name, including file ending (.jpg/.png/etc)
* - If event is online, location will be the platform, with capital first letter and no trailing spaces
* - ie. location="Discord"
* @todo
* get Link component
*/
export function EventDescriptionCard({
location,
poster,
name,
date,
online,
registerLink,
children,
}: Props) {
const platformURL = getPlatformURL(location);
return (
<article className={styles.card}>
{poster && <Image className={styles.poster} src={poster} alt={name} />}
<div className={styles.details}>
<h1 className={styles.name}>{name}</h1>
<h2 className={styles.setting}>
<EventSetting date={date} online={online} location={location} />
</h2>
<div className={styles.desc}>{children}</div>
<div className={styles.spacer}></div>
<footer>
{registerLink && (
<div className={styles.button}>
<button>
<a href={registerLink}>Register</a>
</button>
</div>
)}
{online && platformURL && (
<a target="_blank" href={platformURL} rel="noreferrer">
<Image
className={styles.logo}
alt={location}
src={"logos/" + location + ".png"}
/>
</a>
)}
</footer>
</div>
</article>
);
}

@ -0,0 +1,27 @@
import React from "react";
interface Props {
date: Date;
online: boolean;
location: string;
}
export function EventSetting(props: Props) {
const date = props.date.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
});
const time = props.date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
});
const location = props.online ? `Online - ${props.location}` : props.location;
return (
<div>
<time dateTime={props.date.toISOString()}>{`${date} | ${time}`}</time>
{` | ${location}`}
</div>
);
}

@ -0,0 +1,16 @@
import React, { ImgHTMLAttributes } from "react";
export function Image(props: ImgHTMLAttributes<HTMLImageElement>) {
const { src: relativeSrc = "" } = props;
let absoluteSrc = process.env.BASE_PATH ?? "/";
if (absoluteSrc.endsWith("/") && relativeSrc.startsWith("/")) {
absoluteSrc += relativeSrc.slice(1);
} else if (absoluteSrc.endsWith("/") || relativeSrc.startsWith("/")) {
absoluteSrc += relativeSrc;
} else {
absoluteSrc += "/" + relativeSrc;
}
return <img {...props} src={absoluteSrc} />;
}

@ -1,24 +1,25 @@
.miniEventCard {
max-width: 936px;
max-width: calc(936rem / 16);
box-sizing: border-box;
position: relative;
color: var(--purple-2);
padding: 1.25rem;
font-size: 0.875rem;
padding: calc(20rem / 16);
/* FIXME: Check figma for updated size */
font-size: calc(14rem / 16);
}
.name {
display: flex;
font-size: 1.125rem;
font-size: calc(18rem / 16);
margin: 0;
}
.nameSpacer {
width: 140px;
width: calc(140rem / 16);
}
.info {
margin-top: 0;
margin-bottom: calc(12rem / 16);
}
.details {
@ -27,7 +28,7 @@
right: 0;
cursor: pointer;
color: var(--blue-2);
margin: 1.25rem;
margin: calc(20rem / 16);
}
.miniEventCard[open] .shortDescription {

@ -1,13 +1,14 @@
import React, { ReactNode } from "react";
import { EventSetting } from "./EventSetting";
import styles from "./MiniEventCard.module.css";
interface Props {
name: string;
descriptionShort: string;
description: ReactNode;
short: string;
online: boolean;
location: string;
date: string;
time: string;
date: Date;
}
const dropDownIcon = (
@ -28,11 +29,11 @@ const dropDownIcon = (
export const MiniEventCard: React.FC<Props> = ({
name,
descriptionShort,
short,
description,
location,
date,
time,
online,
}) => {
return (
<details className={styles.miniEventCard}>
@ -42,10 +43,10 @@ export const MiniEventCard: React.FC<Props> = ({
<div>{name}</div>
<div className={styles.nameSpacer}></div>
</h2>
<p className={styles.info}>
{location} | {date} | {time}
</p>
<p className={styles.shortDescription}>{descriptionShort}</p>
<div className={styles.info}>
<EventSetting date={date} location={location} online={online} />
</div>
<p className={styles.shortDescription}>{short}</p>
</div>
<p className={styles.details}>View details {dropDownIcon}</p>

@ -0,0 +1,151 @@
.navbar {
display: flex;
justify-content: center;
align-items: center;
background-color: var(--white);
}
.navContent {
display: flex;
flex-direction: row;
flex-wrap: none;
justify-content: space-between;
align-items: center;
width: stretch;
max-width: calc(1440rem / 16);
height: auto;
padding: calc(28rem / 16) calc(136rem / 16);
}
.logo {
display: flex;
justify-content: center;
align-items: center;
}
.logo:hover {
cursor: pointer;
}
.logo img {
width: calc(96rem / 16);
}
.navMenu {
display: inline-flex;
flex-direction: row;
flex-wrap: none;
justify-content: space-between;
align-items: baseline;
margin: 0;
padding: 0;
width: calc(512rem / 16);
}
.navMenu li {
list-style: none;
text-align: center;
}
.navMenu a {
color: var(--purple-2);
text-decoration: none;
}
.navMenu a.currentPage {
color: var(--blue-2);
}
.navMenu > li:hover > a {
color: var(--blue-2);
font-weight: 600;
}
/* Prevents the menu items from shifting when made bold on hover */
.navMenu > li > a::before {
display: block;
content: attr(title);
font-weight: 600;
height: 0;
overflow: hidden;
visibility: hidden;
}
.navMenu > li > a {
padding: 1rem;
}
.dropdownWrapper {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.dropdown {
visibility: visible;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
position: absolute;
margin: 0;
margin-top: calc(48rem / 16);
padding: 0;
border-radius: calc(8rem / 16);
background-color: var(--white);
box-shadow: 0 calc(8rem / 16) 1rem var(--blue-1-20);
font-size: calc(14rem / 16);
}
.dropdown > li {
width: 100%;
}
.dropdown > li > a {
padding: calc(8rem / 16);
width: 100%;
box-sizing: border-box;
}
.dropdown > li:hover > a,
.dropdown > li > a:focus {
background-color: var(--blue-1-20);
}
.dropdown > li:first-child > a {
padding-top: 1rem;
border-radius: calc(8rem / 16) calc(8rem / 16) 0 0;
}
.dropdown > li:last-child > a {
padding-bottom: 1rem;
border-radius: 0 0 calc(8rem / 16) calc(8rem / 16);
}
.navMenu > li .dropdown {
visibility: hidden;
}
.navMenu > li:hover .dropdown,
.navMenu > li:focus-within .dropdown {
visibility: visible;
}
/* On a smaller desktop screen, keep the same navbar layout but decrease the
* horizontal padding so it still fits
*/
@media screen and (max-width: calc(960rem / 16)) {
.navContent {
padding: calc(28rem / 16) calc(64rem / 16);
}
}

@ -0,0 +1,120 @@
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import { Image } from "./Image";
import styles from "./Navbar.module.css";
interface NavLink {
name: string;
route: string;
submenu?: {
name: string;
route: string;
}[];
}
const menu: NavLink[] = [
{
name: "Home",
route: "/",
},
{
name: "About",
route: "/about",
submenu: [
{
name: "About Us",
route: "/about",
},
{
name: "Meet the Team",
route: "/about/team",
},
{
name: "Constitution",
route: "/about/constitution",
},
{
name: "Code of Conduct",
route: "/about/code-of-conduct",
},
],
},
{
name: "Get Involved",
route: "/get-involved",
},
{
name: "Events",
route: "/events",
},
{
name: "Resources",
route: "/resources",
},
];
function NavItem(props: NavLink) {
const router = useRouter();
return (
<>
<Link href={props.route}>
<a
title={props.name}
className={
router.pathname === props.route ||
((props.submenu?.length ?? 0) > 0 &&
router.pathname.startsWith(props.route))
? styles.currentPage
: ""
}
onClick={() => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
}}
>
{props.name}
</a>
</Link>
{(props.submenu?.length ?? 0) > 0 ? (
<ul className={styles.dropdown}>
{props.submenu?.map((item) => {
return (
<li className={styles.dropdownWrapper} key={item.name}>
<NavItem name={item.name} route={item.route} />
</li>
);
})}
</ul>
) : null}
</>
);
}
export function Navbar() {
return (
<nav className={styles.navbar}>
<div className={styles.navContent}>
<Link href="/">
<a className={styles.logo}>
<Image src="/images/logo-icon.png" alt="CSC Logo" />
</a>
</Link>
<ul className={styles.navMenu}>
{menu.map((item) => {
return (
<li className={styles.dropdownWrapper} key={item.name}>
<NavItem
name={item.name}
route={item.route}
submenu={item.submenu}
/>
</li>
);
})}
</ul>
</div>
</nav>
);
}

@ -0,0 +1,32 @@
.card {
padding: calc(27rem / 16) calc(39rem / 16);
max-width: calc(524rem / 16);
background-color: white;
}
.date {
color: var(--purple-2);
font-size: calc(18rem / 16);
font-weight: bold;
line-height: calc(27rem / 16);
}
.author {
color: var(--purple-1);
font-style: normal;
line-height: calc(21rem / 16);
font-size: calc(14rem / 16);
margin: calc(5rem / 16) 0 calc(7rem / 16) 0;
}
.content {
line-height: calc(21rem / 16);
color: var(--purple-2);
}
@media only screen and (max-width: calc(768rem / 16)) {
.card {
padding: 0;
background-color: transparent;
}
}

@ -0,0 +1,30 @@
import React, { ReactNode } from "react";
import styles from "./NewsCard.module.css";
interface NewsCardProps {
date: Date;
author: string;
children: ReactNode;
}
export const NewsCard: React.FC<NewsCardProps> = ({
date,
author,
children,
}) => {
return (
<article className={styles.card}>
<h3>
<time className={styles.date} dateTime={date.toISOString()}>
{date.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
</time>
</h3>
<address className={styles.author}>{author}</address>
<div className={styles.content}>{children}</div>
</article>
);
};

@ -0,0 +1,28 @@
.container {
max-width: calc(126rem / 16);
display: flex;
flex-direction: column;
margin: 0;
}
.img {
width: 100%;
border-radius: 50%;
margin: 0 auto;
}
.caption {
text-align: center;
margin-top: calc(24rem / 16);
}
.name {
font-weight: bold;
color: var(--blue-1);
}
.role {
font-weight: 600;
color: var(--purple-2);
line-height: 1.875;
}

@ -0,0 +1,29 @@
import React from "react";
import styles from "./TeamMember.module.css";
import { Image } from "./Image";
interface TeamMemberProps {
name: string;
role: string;
image?: string;
}
export const TeamMember: React.FC<TeamMemberProps> = ({
name,
role,
image,
}) => {
return (
<div className={styles.container}>
<Image
className={styles.img}
src={image ?? "/images/team-member-placeholder.svg"}
alt={`Picture of ${name}`}
/>
<div className={styles.caption}>
<div className={styles.name}>{name}</div>
<div className={styles.role}>{role}</div>
</div>
</div>
);
};

@ -0,0 +1,112 @@
.card {
display: grid;
grid-template-columns: calc(126rem / 16) auto;
grid-template-areas:
"picture name"
"picture role"
"picture description";
column-gap: calc(32rem / 16);
row-gap: 0;
justify-items: start;
align-items: start;
max-width: calc(847rem / 16);
}
.picture {
grid-area: picture;
justify-self: center;
max-width: calc(126rem / 16);
max-height: calc(126rem / 16);
clip-path: circle(50%);
}
.image {
width: 100%;
}
.name {
grid-area: name;
margin: 0;
color: var(--blue-1);
font-size: calc(36rem / 16);
line-height: 1.1;
font-weight: 700;
}
.role {
grid-area: role;
margin: 0;
color: var(--purple-2);
font-size: calc(24rem / 16);
line-height: 1.7;
font-weight: 600;
}
.description {
grid-area: description;
margin: 0;
line-height: 1.875;
}
@media screen and (max-width: calc(768rem / 16)) {
.card {
grid-template-columns: calc(90rem / 16) auto;
column-gap: calc(22rem / 16);
max-width: calc(460rem / 16);
}
.picture {
max-width: calc(90rem / 16);
max-height: calc(90rem / 16);
}
.name,
.role,
.description {
line-height: 1.5;
}
}
/* TODO: Use the correct mobile styles from figma
@media only screen and (max-width: calc(375rem / 16)) {
.card {
grid-template-columns: calc(70rem / 16) auto;
grid-template-rows: auto calc(calc(14rem / 16) * 1.5 + calc(12rem / 16)) auto;
grid-template-areas:
"picture name"
"picture role"
"description description";
column-gap: 1.4375rem;
align-items: end;
max-width: calc(190rem / 16);
}
.picture {
max-width: calc(70rem / 16);
max-height: calc(70rem / 16);
}
.name,
.role,
.description {
line-height: 1.5;
}
.role {
margin-bottom: calc(12rem / 16);
}
.description {
justify-self: top;
margin-top: calc(12rem / 16);
margin-left: calc(12rem / 16);
}
} */

@ -0,0 +1,27 @@
import React from "react";
import { Image } from "./Image";
import styles from "./TeamMemberCard.module.css";
interface TeamMemberCardProps {
name: string;
role: string;
image?: string; // path to image of person, relative to public directory
children: React.ReactNode;
}
export function TeamMemberCard(props: TeamMemberCardProps) {
return (
<article className={styles.card}>
<div className={styles.picture}>
<Image
className={styles.image}
src={props.image ?? "/images/team-member-placeholder.svg"}
alt={`Picture of ${props.name}`}
/>
</div>
<h1 className={styles.name}>{props.name}</h1>
<h2 className={styles.role}>{props.role}</h2>
<div className={styles.description}>{props.children}</div>
</article>
);
}

@ -1,3 +1,93 @@
.miniEventCardDemo > *:nth-child(odd) {
background: #E1EEFA;
}
background: #e1eefa;
}
.newsDemo {
padding: calc(50rem / 16);
background-color: var(--off-white);
display: inline-block;
}
.newsTitle {
font-style: normal;
font-weight: bold;
color: var(--purple-2);
font-size: calc(24rem / 16);
line-height: calc(36rem / 16);
margin-bottom: calc(14rem / 16);
}
.newsDesc {
font-style: normal;
font-weight: normal;
font-size: calc(14rem / 16);
line-height: calc(21rem / 16);
white-space: pre-line;
color: var(--purple-2);
vertical-align: baseline;
}
.news > hr {
border: none;
height: calc(1rem / 16);
background-color: var(--purple-2);
margin: 0 0 calc(13rem / 16) 0;
}
.eventDescriptionCardDemo {
padding: calc(50rem / 16) 0;
background-color: var(--off-white);
display: inline-block;
}
.eventDescriptionCardDemo > * {
margin: calc(12rem / 16) calc(50rem / 16);
}
.eventDescriptionCardDemo > *:first-child {
margin-top: 0;
}
.eventDescriptionCardDemo > *:last-child {
margin-bottom: 0;
}
.teamMemberDemo {
padding: calc(10rem / 16) calc(50rem / 16) calc(30rem / 16) calc(50rem / 16);
max-width: calc(847rem / 16);
}
.committee {
margin: 0;
color: var(--purple-2);
font-weight: 600;
font-size: calc(24rem / 16);
line-height: calc(36rem / 16);
}
.teamMemberDemo > hr {
border: none;
height: calc(1rem / 16);
background-color: var(--blue-2);
width: 100%;
margin-top: calc(24rem / 16);
margin-bottom: calc(46rem / 16);
}
.teamMembers {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(calc(100rem / 16), 1fr));
row-gap: calc(43rem / 16);
column-gap: calc(53rem / 16);
}
@media only screen and (max-width: calc(768rem / 16)) {
.newsDemo,
.eventDescriptionCardDemo {
background-color: #e1eefa;
}
.eventDescriptionCardDemo > * {
margin: calc(50rem / 16);
}
}

@ -4,49 +4,125 @@ import styles from "./playground.module.css";
import AfterHoursContent, {
metadata as afterHoursMetadata,
} from "../content/playground/after-hours.event.mdx";
import OOTBReact, {
metadata as OOTBReactEventMetadata,
} from "../content/playground/ootb-react.event.mdx";
import AltTab, {
metadata as altTabEventMetadata,
} from "../content/playground/alt-tab.event.mdx";
import UnavailableContent, {
metadata as unavailableMetadata,
} from "../content/playground/unavailable.news.mdx";
import { metadata as dogeMetadata } from "../content/playground/doge.team-member.mdx";
import CodeyInfo, {
metadata as codeyMetadata,
} from "../content/playground/codey.team-member.mdx";
import { MiniEventCard } from "./MiniEventCard";
import { NewsCard } from "./NewsCard";
import { EventCard } from "./EventCard";
import { EventDescriptionCard } from "./EventDescriptionCard";
import { TeamMember } from "./TeamMember";
import { TeamMemberCard } from "./TeamMemberCard";
import { OrganizedContent, LinkProps } from "./OrganizedContent";
export function MiniEventCardDemo() {
const { name, location, short, date } = afterHoursMetadata;
const dateString = date.toLocaleDateString("en-US", {
day: "numeric",
month: "long",
year: "numeric",
});
const timeString = date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
});
const events = [
{ Content: OOTBReact, metadata: OOTBReactEventMetadata },
{ Content: AfterHoursContent, metadata: afterHoursMetadata },
{ Content: AltTab, metadata: altTabEventMetadata },
];
export function MiniEventCardDemo() {
return (
<div className={styles.miniEventCardDemo}>
<MiniEventCard
name={name}
date={dateString}
time={timeString}
descriptionShort={short}
location={location}
description={<AfterHoursContent />}
/>
<MiniEventCard
name={name}
date={dateString}
time={timeString}
descriptionShort={short}
location={location}
description={<AfterHoursContent />}
/>
<MiniEventCard
name={name}
date={dateString}
time={timeString}
descriptionShort={short}
location={location}
description={<AfterHoursContent />}
/>
{events.map(({ Content, metadata }) => (
<MiniEventCard
{...metadata}
description={<Content />}
key={metadata.name + metadata.date.toString()}
/>
))}
</div>
);
}
export function NewsCardDemo() {
return (
<div className={styles.newsDemo}>
<div className={styles.newsTitle}>News</div>
<div className={styles.newsDesc}>
Updates from our execs
<br />
<br />
</div>
<hr className={styles.newsHr} />
<NewsCard {...unavailableMetadata}>
<UnavailableContent />
</NewsCard>
</div>
);
}
export function EventDescriptionCardDemo() {
return (
<div className={styles.eventDescriptionCardDemo}>
{events.map(({ metadata }) => (
<EventDescriptionCard
{...metadata}
key={metadata.name + metadata.date.toString()}
>
{metadata.short}
</EventDescriptionCard>
))}
</div>
);
}
export function EventCardDemo() {
return (
<>
{events.map(({ Content, metadata }) => (
<EventCard
{...metadata}
key={metadata.name + metadata.date.toDateString()}
>
<Content />
</EventCard>
))}
</>
);
}
export function TeamMemberDemo() {
return (
<div className={styles.teamMemberDemo}>
<div className={styles.teamMemberHeader}>
<h1 className={styles.committee}>Programme Committee</h1>
</div>
<hr />
<div className={styles.teamMembers}>
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
<TeamMember {...dogeMetadata} />
</div>
</div>
);
}
export function TeamMemberCardDemo() {
return (
<div className={styles.teamMemberCardDemo}>
<TeamMemberCard {...codeyMetadata}>
<CodeyInfo />
</TeamMemberCard>
</div>
);
}

@ -2,7 +2,9 @@ export const metadata = {
name: "Afterhours: Personal Relationships",
short: "Learn how React works and make your own version!",
date: new Date("2021-03-02 2:00 PM"),
location: "Online - Twitch",
online: false,
location: "MC",
registerLink: "http://csclub.uwaterloo.ca/",
};
The past year has been tough for all of us, having to deal with the pandemic

@ -0,0 +1,14 @@
export const metadata = {
name: "Alt-Tab",
short: "CSC is proud to present to you Alt-Tab!",
date: new Date("March 25, 2021 19:00:00"),
online: true,
location: "Twitch",
poster: "/images/playground/alt-tab.jpg",
};
CSC is proud to present to you Alt-Tab! Join us in a lightning tech talk series presented to you by our very own students. Alt-Tab consists of 10 to 15-minute talks about anything related to tech. Learn more about exciting topics that range from competitive programming to cryptography!
We will have four incredible presenters that are eager to share their insights with you. Stay tuned as we'll be introducing them and the topics that they will be discussing soon!.
Registration is not required to attend! We'll just be sending you an email reminder, as well as inviting you to our calendar even

@ -0,0 +1,9 @@
export const metadata = {
name: "Codey",
role: "Mascot",
image: "/images/playground/codeyHi.png"
}
The one, the only, Codey! Codey is ecstatic to be your mascot for this term.
Codey loves programming and playing on their laptop. You can often find Codey
posing for event promo graphics, or chilling in the CSC discord.

@ -0,0 +1,5 @@
export const metadata = {
name: "Woof Woof",
role: "Doge",
image: "/images/playground/doge.jpg"
}

@ -0,0 +1,17 @@
export const metadata = {
name: "Out of the Box: React",
short: "Out of the Box is a series of code-along projects that explore what's under the hood of modern web frameworks.",
date: new Date("March 23, 2021 19:00:00"),
online: true,
location: "Twitch",
poster: "/images/playground/intro-ootb.jpg",
registerLink: "http://google.com/",
};
Modern web frameworks are a black-box. They're easy to use, but they have numerous minute details to master in order to apply them to truly scalable websites. Over the last few years, front-end frameworks have absorbed the responsibilities of the back-end, meaning it's become ever more important to dig their details out of the box.
Out of the Box is a series of code-along projects that explore what's under the hood of modern web frameworks. Nearly 5 million websites use React, including many of the internet's most popular websites. While its simple syntax attracts developers from all over, underneath lies a complex infrastructure of code to manage all elements from caching to hooks. Rishi will bring these ideas to light in our inaugural episode of Out of the Box. Come join him and code your own version of React!
Only basic web experience is needed. All JavaScript code will be written within a single HTML document for simplicity. Node.js will also be required to participate in the event!
Registration is not required to attend! We'll just be sending you an email reminder, as well as inviting you to our calendar event.

@ -0,0 +1,14 @@
export const metadata = {
author: "merenber",
date: new Date("2021-03-19"),
}
Computer Science Club systems and services will be unavailable on Saturday, Mar. 20
due to a planned power outage in the Mathematics and Computer Building (MC) from 7am to 5pm.
The CSC will begin shutting down machines at 6am in preparation of the outage.
Please prepare for the outage by:
- Ensuring all running processes have their state saved (configuration, data, etc.)
- Any important files are backed up off-site from the CSC
- If you have any questions/concerns, please email the Systems Committee.

48
next-env.d.ts vendored

@ -1,16 +1,50 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
interface EventMetadata {
name: string;
short: string;
date: Date;
location: string;
}
declare module "*.event.mdx" {
import { ComponentType } from "react";
interface EventMetadata {
name: string;
short: string;
date: Date;
online: boolean;
location: string;
poster?: string;
registerLink?: string;
}
const ReactComponent: ComponentType;
export const metadata: EventMetadata;
export default ReactComponent;
}
declare module "*.news.mdx" {
import { ComponentType } from "react";
interface NewsMetadata {
author: string;
date: Date;
}
const ReactComponent: ComponentType;
export const metadata: NewsMetadata;
export default ReactComponent;
}
declare module "*.team-member.mdx" {
import { ComponentType } from "react";
interface TeamMemberMetadata {
name: string;
role: string;
image?: string;
}
const ReactComponent: ComponentType;
export const metadata: TeamMemberMetadata;
export default ReactComponent;
}

@ -1,7 +1,9 @@
const withMDX = require('@next/mdx')({
extension: /\.mdx$/
})
const withMDX = require("@next/mdx")({
extension: /\.mdx$/,
});
module.exports = withMDX({
pageExtensions: ['ts', 'tsx', 'mdx']
})
pageExtensions: ["ts", "tsx", "mdx"],
trailingSlash: true,
basePath: process.env.BASE_PATH,
});

11835
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -33,6 +33,10 @@
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",