From 4e93c4a9485875ced7bd58856d90bb2a59226d33 Mon Sep 17 00:00:00 2001 From: Michael Fatemi Date: Tue, 5 Jan 2021 22:58:56 -0500 Subject: [PATCH] add officer order, some UI components --- src/components/ArticleList.tsx | 42 ++++++----- src/components/ArticleRow.tsx | 2 +- .../BlockContentWithExternalLinks.tsx | 23 ++++++ src/components/BlueButton.tsx | 15 ++++ src/components/BlueButtonLink.tsx | 23 ++++++ src/components/Centered.tsx | 3 + src/components/InitiativeColumn.tsx | 2 +- src/components/InitiativeRow.tsx | 3 +- src/components/LocalLinkClickable.tsx | 15 ++++ src/components/MemberRow.tsx | 2 +- src/components/ParagraphHeader.tsx | 9 +++ src/components/PrimaryHeader.tsx | 7 ++ src/hooks/useCommittee.tsx | 8 +++ src/hooks/useNewsArticle.ts | 12 ++++ src/{ => lib}/imageUrl.ts | 2 +- src/lib/sortCommittee.ts | 24 +++++++ src/pages/404.tsx | 9 ++- src/pages/classcouncil.tsx | 14 ++-- src/pages/committee.tsx | 16 ++--- src/pages/initiatives.tsx | 12 ++-- src/pages/involved.tsx | 33 ++++----- src/pages/mission.tsx | 72 +++++++++++-------- src/pages/newsArticle.tsx | 57 +++++---------- src/pages/officers.tsx | 40 +++++++---- 24 files changed, 294 insertions(+), 151 deletions(-) create mode 100644 src/components/BlockContentWithExternalLinks.tsx create mode 100644 src/components/BlueButton.tsx create mode 100644 src/components/BlueButtonLink.tsx create mode 100644 src/components/Centered.tsx create mode 100644 src/components/LocalLinkClickable.tsx create mode 100644 src/components/ParagraphHeader.tsx create mode 100644 src/components/PrimaryHeader.tsx create mode 100644 src/hooks/useCommittee.tsx create mode 100644 src/hooks/useNewsArticle.ts rename src/{ => lib}/imageUrl.ts (90%) create mode 100644 src/lib/sortCommittee.ts diff --git a/src/components/ArticleList.tsx b/src/components/ArticleList.tsx index a77eb4c..b451fbd 100644 --- a/src/components/ArticleList.tsx +++ b/src/components/ArticleList.tsx @@ -2,6 +2,7 @@ import React from 'react'; import ArticleRow from './ArticleRow'; import sanity from '../sanity'; import '../css/article.css'; +import BlueButton from './BlueButton'; export default function ArticleList() { let [articles, setArticles] = React.useState([]); @@ -40,27 +41,30 @@ export default function ArticleList() { return null; } + let bottomComponent: any; + if (reachedEnd) { + bottomComponent =
No more articles to show
; + } else { + bottomComponent = ( + { + let { publish_date, title } = articles[articles.length - 1]; + addArticles(publish_date, title); + }} + > + Load more articles + + ); + } + + const articleList = articles.map((article) => ( + + )); + return (
- {articles.map((article) => { - return ; - })} - -
- {!reachedEnd ? ( - - ) : ( -
No more articles to show
- )} -
+ {articleList} +
{bottomComponent}
); } diff --git a/src/components/ArticleRow.tsx b/src/components/ArticleRow.tsx index 0f6ef20..bf0ff4e 100644 --- a/src/components/ArticleRow.tsx +++ b/src/components/ArticleRow.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import imageUrl from '../imageUrl'; +import imageUrl from '../lib/imageUrl'; import { Link } from 'react-router-dom'; import '../css/article.css'; diff --git a/src/components/BlockContentWithExternalLinks.tsx b/src/components/BlockContentWithExternalLinks.tsx new file mode 100644 index 0000000..fee0822 --- /dev/null +++ b/src/components/BlockContentWithExternalLinks.tsx @@ -0,0 +1,23 @@ +import BlockContent from '@sanity/block-content-to-react'; + +export default function BlockContentWithExternalLinks({ + blocks, +}: { + blocks: any[]; +}) { + return ( +
{ + // When this element loads, convert all the links to have target="_blank." + // This ensures that the links open in a new tab + if (ref) { + ref.querySelectorAll('a').forEach((link) => { + link.target = '_blank'; + }); + } + }} + > + +
+ ); +} diff --git a/src/components/BlueButton.tsx b/src/components/BlueButton.tsx new file mode 100644 index 0000000..6800cd4 --- /dev/null +++ b/src/components/BlueButton.tsx @@ -0,0 +1,15 @@ +import { MouseEventHandler } from 'react'; + +export default function BlueButton({ + onClick, + children, +}: { + onClick?: MouseEventHandler; + children: React.ReactNode; +}) { + return ( + + ); +} diff --git a/src/components/BlueButtonLink.tsx b/src/components/BlueButtonLink.tsx new file mode 100644 index 0000000..6d151bb --- /dev/null +++ b/src/components/BlueButtonLink.tsx @@ -0,0 +1,23 @@ +import { Link } from 'react-router-dom'; + +export default function BlueButtonLink({ + href, + children, +}: { + href: string; + children: React.ReactNode; +}) { + if (!href.startsWith('http')) { + return ( + + {children} + + ); + } else { + return ( + + {children} + + ); + } +} diff --git a/src/components/Centered.tsx b/src/components/Centered.tsx new file mode 100644 index 0000000..5409566 --- /dev/null +++ b/src/components/Centered.tsx @@ -0,0 +1,3 @@ +export default function Centered({ children }: { children: React.ReactNode }) { + return
{children}
; +} diff --git a/src/components/InitiativeColumn.tsx b/src/components/InitiativeColumn.tsx index 6862fe5..8bc109c 100644 --- a/src/components/InitiativeColumn.tsx +++ b/src/components/InitiativeColumn.tsx @@ -1,5 +1,5 @@ import BlockContent from '@sanity/block-content-to-react'; -import imageUrl from '../imageUrl'; +import imageUrl from '../lib/imageUrl'; import '../css/initiative.css'; export default function InitiativeColumn({ name, thumbnail, content }) { diff --git a/src/components/InitiativeRow.tsx b/src/components/InitiativeRow.tsx index 5e7f2fd..edc7b38 100644 --- a/src/components/InitiativeRow.tsx +++ b/src/components/InitiativeRow.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import imageUrl from '../imageUrl'; +import imageUrl from '../lib/imageUrl'; import BlockContent from '@sanity/block-content-to-react'; import '../css/article.css'; diff --git a/src/components/LocalLinkClickable.tsx b/src/components/LocalLinkClickable.tsx new file mode 100644 index 0000000..2e0ea9b --- /dev/null +++ b/src/components/LocalLinkClickable.tsx @@ -0,0 +1,15 @@ +import { Link } from 'react-router-dom'; + +export default function LocalLinkClickable({ + to, + children, +}: { + to: string; + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/src/components/MemberRow.tsx b/src/components/MemberRow.tsx index 6cb1405..e4faac6 100644 --- a/src/components/MemberRow.tsx +++ b/src/components/MemberRow.tsx @@ -1,4 +1,4 @@ -import imageUrl from '../imageUrl'; +import imageUrl from '../lib/imageUrl'; import '../css/article.css'; export default function MemberRow({ member }: { member: SGA.MemberDocument }) { diff --git a/src/components/ParagraphHeader.tsx b/src/components/ParagraphHeader.tsx new file mode 100644 index 0000000..73bbc7d --- /dev/null +++ b/src/components/ParagraphHeader.tsx @@ -0,0 +1,9 @@ +export default function ParagraphHeader({ + children, +}: { + children: React.ReactNode; +}) { + return ( +

{children}

+ ); +} diff --git a/src/components/PrimaryHeader.tsx b/src/components/PrimaryHeader.tsx new file mode 100644 index 0000000..868b4e6 --- /dev/null +++ b/src/components/PrimaryHeader.tsx @@ -0,0 +1,7 @@ +export default function PrimaryHeader({ + children, +}: { + children: React.ReactNode; +}) { + return

{children}

; +} diff --git a/src/hooks/useCommittee.tsx b/src/hooks/useCommittee.tsx new file mode 100644 index 0000000..7553e83 --- /dev/null +++ b/src/hooks/useCommittee.tsx @@ -0,0 +1,8 @@ +import useQuery from './useQuery'; + +export default function useCommittee(committee: string) { + return useQuery( + `*[_type == 'member' && committee == $committee]`, + { committee } + ); +} diff --git a/src/hooks/useNewsArticle.ts b/src/hooks/useNewsArticle.ts new file mode 100644 index 0000000..c347bf7 --- /dev/null +++ b/src/hooks/useNewsArticle.ts @@ -0,0 +1,12 @@ +import { useEffect, useState } from 'react'; +import sanity from '../sanity'; + +export default function useNewsArticle(articleId: string) { + let [article, setArticle] = useState(null!); + + useEffect(() => { + sanity.fetch('*[_id == $articleId] [0]', { articleId }).then(setArticle); + }, [articleId]); + + return article; +} diff --git a/src/imageUrl.ts b/src/lib/imageUrl.ts similarity index 90% rename from src/imageUrl.ts rename to src/lib/imageUrl.ts index 4b5828e..c9762f9 100644 --- a/src/imageUrl.ts +++ b/src/lib/imageUrl.ts @@ -1,5 +1,5 @@ import { default as ImageUrlBuilder } from '@sanity/image-url'; -import sanity from './sanity'; +import sanity from '../sanity'; const builder = ImageUrlBuilder(sanity); diff --git a/src/lib/sortCommittee.ts b/src/lib/sortCommittee.ts new file mode 100644 index 0000000..3d9a750 --- /dev/null +++ b/src/lib/sortCommittee.ts @@ -0,0 +1,24 @@ +export default function sortCommittee( + members: SGA.MemberDocument[], + roleOrder: string[] +) { + const roleIndexes = {}; + for (const { _id, role } of members) { + roleIndexes[_id] = roleOrder.findIndex((role_) => role_ === role); + } + + return members.sort((a, b) => { + let roleDifference = roleIndexes[a._id] - roleIndexes[b._id]; + if (roleDifference !== 0) { + return roleDifference; + } else { + if (a.name < b.name) { + return -1; + } else if (a.name > b.name) { + return 1; + } else { + return 0; + } + } + }); +} diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 06487a9..5b060ed 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -1,8 +1,11 @@ +import Centered from '../components/Centered'; +import PrimaryHeader from '../components/PrimaryHeader'; + export default function NotFoundPage() { return ( -
-

404: Not Found

+ + 404: Not Found

This page wasn't found...

-
+ ); } diff --git a/src/pages/classcouncil.tsx b/src/pages/classcouncil.tsx index 361490f..cf2ce4d 100644 --- a/src/pages/classcouncil.tsx +++ b/src/pages/classcouncil.tsx @@ -4,18 +4,18 @@ import MemberRow from '../components/MemberRow'; import useQuery from '../hooks/useQuery'; export default function ClassCouncil() { - let members = useQuery( - `*[_type == 'member' && role == 'class'] | order (year desc)` - ); + let members = + useQuery( + `*[_type == 'member' && role == 'class'] | order (year desc)` + ) ?? []; return ( <>
- {members && - members.map((member) => { - return ; - })} + {members.map((member) => ( + + ))}
); diff --git a/src/pages/committee.tsx b/src/pages/committee.tsx index b5729d3..2ebb424 100644 --- a/src/pages/committee.tsx +++ b/src/pages/committee.tsx @@ -4,9 +4,10 @@ import MemberRow from '../components/MemberRow'; import useQuery from '../hooks/useQuery'; export default function Committee() { - let excomm = useQuery( - `*[_type == 'member' && committee == 'excomm'] | order (role, year desc)` - ); + let excomm = + useQuery( + `*[_type == 'member' && committee == 'excomm'] | order (role, year desc)` + ) ?? []; // year desc because seniority 8) return ( @@ -16,12 +17,9 @@ export default function Committee() { imageURL='/images/who-we-are/excomm.png' />
-
- {excomm && - excomm.map((member) => { - return ; - })} -
+ {excomm.map((member) => ( + + ))}
); diff --git a/src/pages/initiatives.tsx b/src/pages/initiatives.tsx index 079b66e..f5138d1 100644 --- a/src/pages/initiatives.tsx +++ b/src/pages/initiatives.tsx @@ -4,19 +4,17 @@ import InitiativeRow from '../components/InitiativeRow'; import useQuery from '../hooks/useQuery'; export default function Initiatives() { - let initiatives = useQuery( - '*[_type == "initiative"]' - ); + let initiatives = + useQuery('*[_type == "initiative"]') ?? []; return ( <>
- {initiatives && - initiatives.map((initiative) => { - return ; - })} + {initiatives.map((initiative) => ( + + ))}
diff --git a/src/pages/involved.tsx b/src/pages/involved.tsx index feefb16..9074fbb 100644 --- a/src/pages/involved.tsx +++ b/src/pages/involved.tsx @@ -1,25 +1,28 @@ import { SanityDocument } from '@sanity/client'; import React from 'react'; -import { Link } from 'react-router-dom'; +import BlueButtonLink from '../components/BlueButtonLink'; import GetInvolvedRow from '../components/GetInvolvedRow'; import Hero from '../components/Hero'; +import ParagraphHeader from '../components/ParagraphHeader'; import '../css/get-involved.css'; import sanity from '../sanity'; export default function GetInvolved() { - let [ways, setWays] = React.useState< + let [getInvolved, setGetInvolved] = React.useState< SanityDocument | undefined >(); React.useEffect(() => { - sanity.getDocument('get_involved').then(setWays); + sanity + .getDocument('get_involved') + .then(setGetInvolved); }, []); return ( <>
-

SGA Calendar

+ SGA Calendar