Merge remote-tracking branch 'origin/main' into feat/team-member-card

This commit is contained in:
Aditya Thakral 2021-05-24 04:41:25 -04:00
commit 22547eaca1
19 changed files with 384 additions and 120 deletions

2
.gitignore vendored
View File

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

View File

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

48
components/EventCard.tsx Normal file
View File

@ -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}>
<h2>{name}</h2>
<h3>
<EventSetting date={date} online={online} location={location} />
</h3>
<div>{children}</div>
</section>
</article>
);
}

View File

@ -15,6 +15,7 @@
.details {
position: relative;
width: 100%;
}
.name {
@ -28,6 +29,7 @@
.desc {
color: var(--purple-2);
font-size: 0.75rem;
margin-top: 0.75rem;
}
.spacer {
@ -47,6 +49,13 @@
right: 0;
}
.setting {
margin: 0;
color: var(--blue-1);
font-weight: bolder;
font-size: 0.75rem;
}
@media only screen and (max-width: 768px) {
.card {
padding: 0;

View File

@ -4,26 +4,30 @@ import { Image } from "./Image";
import { EventSetting } from "./EventSetting";
import styles from "./EventDescriptionCard.module.css";
interface BaseProps {
interface Props {
name: string;
online: boolean;
location: string;
date: Date;
poster: string;
poster?: string;
registerLink?: string;
children: ReactNode;
}
type Props = BaseProps &
(
| { online: true; location: keyof typeof links }
| { online: false; location: string }
);
const links = {
Twitch: "https://www.twitch.tv/uwcsclub",
Discord: "https://discord.gg/pHfYBCg",
Facebook: "https://www.facebook.com/uw.computerscienceclub",
Instagram: "https://www.instagram.com/uwcsclub/",
};
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
@ -35,36 +39,43 @@ const links = {
* @todo
* get Link component
*/
export function EventDescriptionCard(props: Props) {
export function EventDescriptionCard({
location,
poster,
name,
date,
online,
registerLink,
children,
}: Props) {
const platformURL = getPlatformURL(location);
return (
<article className={styles.card}>
<Image className={styles.poster} src={props.poster} alt={props.name} />
{poster && <Image className={styles.poster} src={poster} alt={name} />}
<div className={styles.details}>
<h3 className={styles.name}>{props.name}</h3>
<EventSetting
date={props.date}
online={props.online}
location={props.location}
/>
<div className={styles.desc}>{props.children}</div>
<h3 className={styles.name}>{name}</h3>
<h4 className={styles.setting}>
<EventSetting date={date} online={online} location={location} />
</h4>
<div className={styles.desc}>{children}</div>
<div className={styles.spacer}></div>
<footer>
{props.registerLink && (
{registerLink && (
<div className={styles.button}>
<button>
<a href={props.registerLink}>Register</a>
<a href={registerLink}>Register</a>
</button>
</div>
)}
{props.online && (
<a target="_blank" href={links[props.location]} rel="noreferrer">
{online && platformURL && (
<a target="_blank" href={platformURL} rel="noreferrer">
<Image
className={styles.logo}
alt={props.location}
src={"logos/" + props.location + ".png"}
alt={location}
src={"logos/" + location + ".png"}
/>
</a>
)}

View File

@ -1,5 +0,0 @@
.setting {
color: var(--blue-1);
font-weight: bolder;
font-size: 0.75rem;
}

View File

@ -1,5 +1,4 @@
import React from "react";
import styles from "./EventSetting.module.css";
interface Props {
date: Date;
@ -20,7 +19,7 @@ export function EventSetting(props: Props) {
const location = props.online ? `Online - ${props.location}` : props.location;
return (
<div className={styles.setting}>
<div>
<time dateTime={props.date.toISOString()}>{`${date} | ${time}`}</time>
{` | ${location}`}
</div>

View File

@ -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}>
@ -43,9 +44,9 @@ export const MiniEventCard: React.FC<Props> = ({
<div className={styles.nameSpacer}></div>
</h2>
<p className={styles.info}>
{location} | {date} | {time}
<EventSetting date={date} location={location} online={online} />
</p>
<p className={styles.shortDescription}>{descriptionShort}</p>
<p className={styles.shortDescription}>{short}</p>
</div>
<p className={styles.details}>View details {dropDownIcon}</p>

View File

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

21
components/TeamMember.tsx Normal file
View File

@ -0,0 +1,21 @@
import React from "react";
import styles from "./TeamMember.module.css";
import { Image } from "./Image";
interface TeamMemberProps {
name: string;
role: string;
src: string;
}
export const TeamMember: React.FC<TeamMemberProps> = ({ name, role, src }) => {
return (
<div className={styles.container}>
<Image className={styles.img} src={src} alt={`${name} | ${role}`} />
<div className={styles.caption}>
<div className={styles.name}>{name}</div>
<div className={styles.role}>{role}</div>
</div>
</div>
);
};

View File

@ -2,7 +2,7 @@
background: #e1eefa;
}
.news {
.newsDemo {
padding: 50px;
background-color: var(--off-white);
display: inline-block;
@ -52,8 +52,37 @@
margin-bottom: 0;
}
.teamMemberDemo {
padding: 10px 50px 30px 50px;
max-width: 847px;
}
.committee {
margin: 0;
color: var(--purple-2);
font-weight: 600;
font-size: 24px;
line-height: 36px;
}
.teamMemberDemo > hr {
border: none;
height: 1px;
background-color: var(--blue-2);
width: 100%;
margin-top: 24px;
margin-bottom: 46px;
}
.teamMembers {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
row-gap: 2.6875rem;
column-gap: 3.3125rem;
}
@media only screen and (max-width: 768px) {
.news,
.newsDemo,
.eventDescriptionCardDemo {
background-color: #e1eefa;
}

View File

@ -1,64 +1,51 @@
import React from "react";
import { EventDescriptionCard } from "./EventDescriptionCard";
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 teamMemberMetadata } from "../content/playground/demo.teammember.mdx";
import { MiniEventCard } from "./MiniEventCard";
import { NewsCard } from "./NewsCard";
import { EventCard } from "./EventCard";
import { EventDescriptionCard } from "./EventDescriptionCard";
import { TeamMember } from "./TeamMember";
const events = [
{ Content: OOTBReact, metadata: OOTBReactEventMetadata },
{ Content: AfterHoursContent, metadata: afterHoursMetadata },
{ Content: AltTab, metadata: altTabEventMetadata },
];
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",
});
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.news}>
<div className={styles.newsDemo}>
<div className={styles.newsTitle}>News</div>
<div className={styles.newsDesc}>
Updates from our execs
@ -74,40 +61,54 @@ export function NewsCardDemo() {
}
export function EventDescriptionCardDemo() {
const { name, short, date } = afterHoursMetadata;
return (
<div className={styles.eventDescriptionCardDemo}>
<EventDescriptionCard
name={name}
date={date}
online={true}
location="Twitch"
poster="/images/playground/intro-ootb.jpg"
registerLink="/"
>
<p>{short}</p>
</EventDescriptionCard>
<EventDescriptionCard
name={name}
date={date}
online={true}
location="Twitch"
poster="/images/playground/alt-tab.jpg"
registerLink="/"
>
<p>{short}</p>
</EventDescriptionCard>
<EventDescriptionCard
name={name}
date={date}
online={true}
location="Twitch"
poster="/images/playground/intro-ootb.jpg"
registerLink="/"
>
<p>{short}</p>
</EventDescriptionCard>
{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 {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
<TeamMember {...teamMemberMetadata} />
</div>
</div>
);
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
export const metadata = {
name: "Name Name",
role: "Role",
src: "images/playground/team-member.png"
}

View File

@ -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.

18
next-env.d.ts vendored
View File

@ -8,7 +8,10 @@ declare module "*.event.mdx" {
name: string;
short: string;
date: Date;
online: boolean;
location: string;
poster?: string;
registerLink?: string;
}
const ReactComponent: ComponentType;
@ -30,3 +33,18 @@ declare module "*.news.mdx" {
export const metadata: NewsMetadata;
export default ReactComponent;
}
declare module "*.teammember.mdx" {
import { ComponentType } from "react";
interface TeamMemberMetadata {
name: string;
role: string;
src: string;
}
const ReactComponent: ComponentType;
export const metadata: TeamMemberMetadata;
export default ReactComponent;
}

View File

@ -2,6 +2,8 @@ import {
MiniEventCardDemo,
NewsCardDemo,
EventDescriptionCardDemo,
EventCardDemo,
TeamMemberDemo
} from "../components/playground";
import { TeamMemberCard } from "../components/TeamMemberCard";
@ -34,6 +36,24 @@ The `<EventDescriptionCard />` component is used on the home page, and uses the
---
## `<EventCard />`
The `<EventCard />` component is used on the events page, and uses the
`<Button />` and `<EventSetting />` components.
<EventCardDemo />
---
## `<TeamMember />`
The `<TeamMember />` component has an image of the team member along with their name and role.
It is used on the Meet the Team page for non executive members.
<TeamMemberDemo />
---
## `<TeamMemberCard />`
The `<TeamMemberCard />` component is used on the "Meet the Team!" page to
@ -44,5 +64,3 @@ display information about the execs: prez, VP, trez, AVP, and syscom overlord.
Codey loves programming and playing on their laptop. You can often find Codey
posing for event promo graphics, or chilling in the CSC discord.
</TeamMemberCard>
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B