Skip to content

Commit

Permalink
feat(config): Refactor our config for proper typechecking (#29)
Browse files Browse the repository at this point in the history
This pr refactors our config file to abstract it via a `config.ts` file,
instead of importing `config.yaml` you will now import `config.ts`, This
file ensures our yaml is properly typechecked and allows us to provide
real types, meaning we can have a single source of truth for things like
enum values.

While writing this pr, I noticed that we do not use the same casing
throughout our config so I refactored things so they are logical,
additionally I went through and simplified some conmponents making sure
their usage of our config reflects the actual config layout. The new
standard for our config is `snake_case` as it is common in `yaml`.

I formatted `config.ts` with a bunch of spaces around our file
validation as if you mess up the config it shows the validation line
instead of the config error line sadly (I have no way of really fixing
this), but this makes the error less confusing for non developers.


This pr closes: #25
  • Loading branch information
spotandjake authored Aug 17, 2024
1 parent 1e21113 commit ecc80b0
Show file tree
Hide file tree
Showing 14 changed files with 746 additions and 305 deletions.
43 changes: 12 additions & 31 deletions components/EventBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,24 @@
// CSS
import styles from '../styles/components/EventBanner.module.scss';
// Config
import config from '../config.yaml';
import { website_config } from '../config';
import ReactMarkdown from 'react-markdown';

interface Props {
color?: string;
contextKey?: keyof typeof config;
}

export default function EventBanner({
color = 'event-banner',
contextKey = 'bannerInfo',
}: Props) {
const bannerInfo = config[contextKey];
export default function EventBanner({ color = 'event-banner' }: Props) {
const { banner_text } = website_config;
if (banner_text == undefined) return null;
if (banner_text.length == 0) return null;

if (contextKey === 'bannerInfo') {
const bannerInfoTyped = bannerInfo as typeof config.bannerInfo;
if (!bannerInfoTyped || bannerInfoTyped.hidden) {
return null;
}

const eventMarkdown = bannerInfoTyped.text;

if (!eventMarkdown) {
return null;
}

return (
<div className={styles.EventBanner} style={{ backgroundColor: color }}>
{/* Event Content */}
<div className={styles.EventContent}>
<ReactMarkdown className={styles.Markdown}>
{eventMarkdown}
</ReactMarkdown>
</div>
return (
<div className={styles.EventBanner} style={{ backgroundColor: color }}>
{/* Event Content */}
<div className={styles.EventContent}>
<ReactMarkdown className={styles.Markdown}>{banner_text}</ReactMarkdown>
</div>
);
}

return null;
</div>
);
}
20 changes: 11 additions & 9 deletions components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
import styles from '../styles/components/Footer.module.scss';
import config from '../config.yaml';
import Button, { ButtonType } from '../components/Button';
import Link from 'next/link';
import { footer } from '../config.yaml';
import { website_config, footer_config } from '../config';
import ReactMarkdown from 'react-markdown';
import Logo from '../components/Logo';

export default function Footer() {
const { social_icons } = website_config;
const { text } = footer_config;
// ui
return (
<footer className={styles.Footer}>
{/* Top section */}
<div className={styles.top}>
<ReactMarkdown className={styles.text}>{footer.text}</ReactMarkdown>
<ReactMarkdown className={styles.text}>{text}</ReactMarkdown>
</div>
{/* Left side */}
<div className={styles.left}>
<div className={styles.logo}>
<Logo />
</div>
<Link href={`mailto:${config.email}`} className={styles.link}>
{config.email}
<Link href={`mailto:${website_config.email}`} className={styles.link}>
{website_config.email}
</Link>
</div>
{/* Right side */}
<div className={styles.right}>
<div className={styles.socialMedia}>
{config.heroIcons.map((icon, index) => (
{social_icons.map(({ alt_text, link, path }, i) => (
<Button
key={index}
image={{ src: icon.path, altText: icon.altText }}
key={i}
image={{ src: path, altText: alt_text }}
type={ButtonType.SOCIAL_DARK}
href={icon.link}
href={link}
className={styles.socialMedia}
/>
))}
Expand Down
15 changes: 9 additions & 6 deletions components/HeroBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
// CSS
import styles from '../styles/components/HeroBanner.module.scss';
import Button, { ButtonType } from './Button';
import { heroIcons, tagline } from '../config.yaml';
import Logo from '../components/Logo';
import { website_config } from '../config';

export default function HeroBanner() {
const { title, social_icons, tagline } = website_config;
// ui
return (
<div className={styles.HeroBanner}>
{/* Left Column */}
<div className={styles.leftColumn}>
<Logo />
<Button type={ButtonType.LIGHT} label='Apply' />
<Button type={ButtonType.LIGHT} label='Apply' href={'/Contact'} />
</div>
{/* Right Column */}
<div className={styles.rightColumn}>
<h1>Trent Computer Science Club Association</h1>
<h1>{title}</h1>
<hr />
<div className={styles.tagline}>{tagline}</div>
<div className={styles.socialMedia}>
{heroIcons.map((icon) => (
{social_icons.map(({ alt_text, link, path }, i) => (
<Button
key={icon.altText}
key={i}
href={link}
type={ButtonType.SOCIAL}
image={{ src: icon.path, altText: icon.altText }}
image={{ src: path, altText: alt_text }}
/>
))}
</div>
Expand Down
16 changes: 9 additions & 7 deletions components/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// CSS
import styles from '../styles/components/NavBar.module.scss';
// Config
import { pageInfo } from '../config.yaml';
import { page_list } from '../config';
// Components
import Button, { ButtonType } from '../components/Button';

Expand All @@ -12,22 +12,24 @@ interface Props {
export default function NavBar(props: Props) {
// Build The Nav
const navContent: JSX.Element[] = [];
pageInfo.forEach((page, index) => {
if (!page.displayInNav) return;
page_list.forEach((page, index) => {
if (!page.display_in_navbar) return;
navContent.push(
<li
key={index}
className={props.currentPage == page.pageName ? styles.currentPage : ''}
className={
props.currentPage == page.page_name ? styles.currentPage : ''
}
>
<Button
type={ButtonType.NAVBAR}
href={page.pageLink}
href={page.page_link}
className={
props.currentPage == page.pageName
props.currentPage == page.page_name
? ButtonType.NAVBAR_ACTIVE
: ButtonType.NAVBAR
}
label={page.pageName}
label={page.page_name}
/>
</li>
);
Expand Down
71 changes: 0 additions & 71 deletions config.d.ts

This file was deleted.

Loading

0 comments on commit ecc80b0

Please sign in to comment.