mirror of
https://github.com/tjsga/tj-sga-website-react.git
synced 2025-04-09 22:50:17 -04:00
more ui
This commit is contained in:
parent
4e93c4a948
commit
b966fc92b7
15
src/App.css
15
src/App.css
|
@ -50,4 +50,19 @@ a.blue-button {
|
|||
.clickable-link {
|
||||
text-decoration: underline;
|
||||
color: #38A3BD;
|
||||
}
|
||||
|
||||
.strong-paragraph {
|
||||
color: #444;
|
||||
font-size: 22px;
|
||||
line-height: 33px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.paragraph-with-header-header {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
display: block;
|
||||
padding-right: 2em;
|
||||
}
|
|
@ -3,6 +3,7 @@ import ArticleRow from './ArticleRow';
|
|||
import sanity from '../sanity';
|
||||
import '../css/article.css';
|
||||
import BlueButton from './BlueButton';
|
||||
import Centered from './Centered';
|
||||
|
||||
export default function ArticleList() {
|
||||
let [articles, setArticles] = React.useState<SGA.ArticleDocument[]>([]);
|
||||
|
@ -64,7 +65,7 @@ export default function ArticleList() {
|
|||
return (
|
||||
<div>
|
||||
{articleList}
|
||||
<div className='text-center'>{bottomComponent}</div>
|
||||
<Centered>{bottomComponent}</Centered>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import React from 'react';
|
||||
import React, { DetailedHTMLProps } from 'react';
|
||||
import imageUrl from '../lib/imageUrl';
|
||||
import { Link } from 'react-router-dom';
|
||||
import '../css/article.css';
|
||||
import ClickableLink from './ClickableLink';
|
||||
|
||||
export default function ArticleRow({
|
||||
article,
|
||||
}: {
|
||||
article: SGA.ArticleDocument;
|
||||
}) {
|
||||
let thumbUrl: string | null = null;
|
||||
let thumbnail: React.ReactElement | null = null;
|
||||
if (article.thumbnail) {
|
||||
thumbUrl = imageUrl(article.thumbnail).url();
|
||||
thumbnail = (
|
||||
<img src={imageUrl(article.thumbnail).url()} alt={article.title} />
|
||||
);
|
||||
}
|
||||
|
||||
const slug = (s: string) => {
|
||||
|
@ -19,22 +21,22 @@ export default function ArticleRow({
|
|||
|
||||
return (
|
||||
<div className='d-flex my-4'>
|
||||
<div className='article-row-thumbnail'>
|
||||
{thumbUrl ? <img src={thumbUrl} alt={article.title} /> : null}
|
||||
</div>
|
||||
<div className='article-row-thumbnail'>{thumbnail}</div>
|
||||
<div className='article-row-content'>
|
||||
<Link
|
||||
to={'/news/' + article._id + '/' + slug(article.title)}
|
||||
className='clickable-link'
|
||||
<ClickableLink
|
||||
href={'/news/' + article._id + '/' + slug(article.title)}
|
||||
target='_blank'
|
||||
>
|
||||
<h3 style={{ margin: '0px' }}>{article.title}</h3>
|
||||
</Link>
|
||||
</ClickableLink>
|
||||
|
||||
<i className='text-sm'>{article.publish_date}</i>
|
||||
<br />
|
||||
<i>{article.author || 'No author'}</i>
|
||||
|
||||
<i>{article.author ?? 'No author'}</i>
|
||||
<br />
|
||||
<p style={{ marginBottom: '0px' }}>{article.summary}</p>
|
||||
|
||||
<p>{article.summary}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
25
src/components/ClickableLink.tsx
Normal file
25
src/components/ClickableLink.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default function ClickableLink({
|
||||
href,
|
||||
children,
|
||||
target,
|
||||
}: {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
target?: string;
|
||||
}) {
|
||||
if (href.startsWith('http')) {
|
||||
return (
|
||||
<a href={href} className='clickable-link' target={target}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Link to={href} className='clickable-link'>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
9
src/components/FlexColumn.tsx
Normal file
9
src/components/FlexColumn.tsx
Normal file
|
@ -0,0 +1,9 @@
|
|||
export default function FlexColumn({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>{children}</div>
|
||||
);
|
||||
}
|
|
@ -17,13 +17,11 @@ export default function Footer() {
|
|||
alt='Footer Banner'
|
||||
/>
|
||||
<div className='footer-container'>
|
||||
{footer.columns.map((col, index) => {
|
||||
return (
|
||||
<div className='footer-col' key={index}>
|
||||
<BlockContent blocks={col.content} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{footer.columns.map((col, index) => (
|
||||
<div className='footer-col' key={index}>
|
||||
<BlockContent blocks={col.content} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
export default function GetInvolvedRow({ way }: { way: SGA.GetInvolvedWay }) {
|
||||
return (
|
||||
<div className='d-flex text-left my-4'>
|
||||
<div className='get-involved-title'>
|
||||
<h3>{way.title}</h3>
|
||||
</div>
|
||||
<div className='get-involved-description'>
|
||||
<p className='get-involved-body'>{way.text}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,14 +1,12 @@
|
|||
import '../css/hero.css';
|
||||
|
||||
type HeroProps = {
|
||||
imageURL?: string;
|
||||
heading?: string;
|
||||
};
|
||||
|
||||
export default function Hero({
|
||||
imageURL = '/images/hero.jpg',
|
||||
heading = 'TJHSST SGA',
|
||||
}: HeroProps) {
|
||||
}: {
|
||||
imageURL?: string;
|
||||
heading?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className='hero'>
|
||||
<span className='hero-heading'>{heading}</span>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default function LocalLinkClickable({
|
||||
to,
|
||||
children,
|
||||
}: {
|
||||
to: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<Link to={to} className='clickable-link'>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
|
@ -1,21 +1,20 @@
|
|||
import imageUrl from '../lib/imageUrl';
|
||||
import '../css/article.css';
|
||||
import RowItemHeader from './RowItemHeader';
|
||||
|
||||
export default function MemberRow({ member }: { member: SGA.MemberDocument }) {
|
||||
let thumbUrl: string | null = null;
|
||||
let thumbnail: React.ReactElement | null = null;
|
||||
if (member.profile_photo) {
|
||||
thumbUrl = imageUrl(member.profile_photo).url();
|
||||
thumbnail = (
|
||||
<img src={imageUrl(member.profile_photo).url()} alt={member.name} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='d-flex my-4'>
|
||||
<div className='article-row-thumbnail'>
|
||||
{thumbUrl ? (
|
||||
<img className='mb-4' src={thumbUrl} alt={member.name} />
|
||||
) : null}
|
||||
</div>
|
||||
<div className='article-row-thumbnail'>{thumbnail}</div>
|
||||
<div className='article-row-content'>
|
||||
<h3>{member.name}</h3>
|
||||
<RowItemHeader>{member.name}</RowItemHeader>
|
||||
<i>
|
||||
{member.role}, {member.year}
|
||||
</i>
|
||||
|
|
20
src/components/ParagraphWithHeader.tsx
Normal file
20
src/components/ParagraphWithHeader.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
import StrongParagraph from './StrongParagraph';
|
||||
|
||||
export default function ParagraphWithHeader({
|
||||
title,
|
||||
body,
|
||||
}: {
|
||||
title: string;
|
||||
body: string;
|
||||
}) {
|
||||
return (
|
||||
<div style={{ display: 'flex', textAlign: 'left' }}>
|
||||
<div className='flex-1 p-2'>
|
||||
<span className='paragraph-with-header-header'>{title}</span>
|
||||
</div>
|
||||
<div className='flex-2 p-2'>
|
||||
<StrongParagraph>{body}</StrongParagraph>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -2,22 +2,22 @@ import React from 'react';
|
|||
import { Link } from 'react-router-dom';
|
||||
import useQuery from '../hooks/useQuery';
|
||||
import ArticleRow from './ArticleRow';
|
||||
import PrimaryHeader from './PrimaryHeader';
|
||||
|
||||
export default function RecentNews() {
|
||||
let news = useQuery<SGA.ArticleDocument[]>(
|
||||
`*[_type == 'article'] | order (publish_date desc, title) [0...3]`
|
||||
);
|
||||
const articles =
|
||||
useQuery<SGA.ArticleDocument[]>(
|
||||
`*[_type == 'article'] | order (publish_date desc, title) [0...3]`
|
||||
) ?? [];
|
||||
|
||||
if (!news) {
|
||||
return null;
|
||||
}
|
||||
const articleList = articles.map((article) => (
|
||||
<ArticleRow article={article} key={article._id} />
|
||||
));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className='display-3'>Recent News</h3>
|
||||
{news.map((article) => {
|
||||
return <ArticleRow article={article} key={article._id} />;
|
||||
})}
|
||||
<PrimaryHeader>Recent News</PrimaryHeader>
|
||||
{articleList}
|
||||
<Link to='/news'>All News</Link>
|
||||
</div>
|
||||
);
|
||||
|
|
7
src/components/RowItemHeader.tsx
Normal file
7
src/components/RowItemHeader.tsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
export default function RowItemHeader({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return <h3 className='header'>{children}</h3>;
|
||||
}
|
|
@ -1,15 +1,28 @@
|
|||
import { Link } from 'react-router-dom';
|
||||
import '../css/segment.css';
|
||||
import BlueButtonLink from './BlueButtonLink';
|
||||
|
||||
export default function InfoColumn({ title, content, imageURL, infoURL }) {
|
||||
function SegmentHeader({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<h3
|
||||
style={{
|
||||
margin: '1em 0px',
|
||||
fontSize: '1.75rem',
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</h3>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Segment({ title, content, imageURL, infoURL }) {
|
||||
return (
|
||||
<div className='segment'>
|
||||
<h3 className='segment-title'>{title}</h3>
|
||||
<SegmentHeader>{title}</SegmentHeader>
|
||||
<img src={imageURL} alt={title} />
|
||||
<p className='segment-body'>{content}</p>
|
||||
<Link to={infoURL} className='blue-button'>
|
||||
MORE INFO
|
||||
</Link>
|
||||
<p className='strong-paragraph'>{content}</p>
|
||||
|
||||
<BlueButtonLink href={infoURL}>MORE INFO</BlueButtonLink>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
7
src/components/StrongParagraph.tsx
Normal file
7
src/components/StrongParagraph.tsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
export default function StrongParagraph({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return <p className='strong-paragraph'>{children}</p>;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
.get-involved-body {
|
||||
color: #444;
|
||||
font-size: 22px;
|
||||
line-height: 33px;
|
||||
font-weight: 300;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.get-involved-title {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
.get-involved-description {
|
||||
flex: 3;
|
||||
}
|
|
@ -10,20 +10,6 @@
|
|||
line-height: 44px;
|
||||
}
|
||||
|
||||
.mission-header {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
display: block;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
.mission-para {
|
||||
font-size: 22px;
|
||||
line-height: 33px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.mission-quote {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import FlexColumn from '../components/FlexColumn';
|
||||
import Hero from '../components/Hero';
|
||||
import InitiativeRow from '../components/InitiativeRow';
|
||||
import useQuery from '../hooks/useQuery';
|
||||
|
@ -11,11 +12,11 @@ export default function Initiatives() {
|
|||
<>
|
||||
<Hero heading='Initiatives' />
|
||||
<main>
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<FlexColumn>
|
||||
{initiatives.map((initiative) => (
|
||||
<InitiativeRow initiative={initiative} />
|
||||
))}
|
||||
</div>
|
||||
</FlexColumn>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { SanityDocument } from '@sanity/client';
|
||||
import React from 'react';
|
||||
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 ParagraphWithHeader from '../components/ParagraphWithHeader';
|
||||
import StrongParagraph from '../components/StrongParagraph';
|
||||
import sanity from '../sanity';
|
||||
|
||||
export default function GetInvolved() {
|
||||
|
@ -23,25 +23,34 @@ export default function GetInvolved() {
|
|||
<Hero heading='Get Involved' />
|
||||
<main className='text-center'>
|
||||
<ParagraphHeader>SGA Calendar</ParagraphHeader>
|
||||
|
||||
<iframe
|
||||
src='https://calendar.google.com/calendar/u/0/embed?src=mbftfg4hu7i8ueqrgcb5o7hc6k@group.calendar.google.com&ctz=America/New_York'
|
||||
title='SGA Calendar'
|
||||
width='800'
|
||||
height='600'
|
||||
/>
|
||||
<p className='get-involved-body my-4'>
|
||||
|
||||
<br />
|
||||
|
||||
<StrongParagraph>
|
||||
Interested in getting involved with SGA? You can run for office, work
|
||||
on a project, or apply to a committee. If you just want to share an
|
||||
idea or concern or get to know your representatives, reach out to us
|
||||
at <b>sga@tjhsst.edu</b>!
|
||||
</p>
|
||||
</StrongParagraph>
|
||||
|
||||
<ParagraphHeader>
|
||||
Here are some ways to connect with SGA:
|
||||
</ParagraphHeader>
|
||||
|
||||
{getInvolved
|
||||
? getInvolved.ways.map((way) => (
|
||||
<GetInvolvedRow way={way} key={way._id} />
|
||||
<ParagraphWithHeader
|
||||
title={way.title}
|
||||
body={way.text}
|
||||
key={way._id}
|
||||
/>
|
||||
))
|
||||
: null}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import useMission from '../hooks/useMission';
|
|||
import '../css/mission.css';
|
||||
import BlueButtonLink from '../components/BlueButtonLink';
|
||||
import Centered from '../components/Centered';
|
||||
import ParagraphWithHeader from '../components/ParagraphWithHeader';
|
||||
|
||||
function MissionQuote({ text, author }) {
|
||||
return (
|
||||
|
@ -16,19 +17,6 @@ function MissionQuote({ text, author }) {
|
|||
);
|
||||
}
|
||||
|
||||
function MissionParagraph({ title, body }: { title: string; body: string }) {
|
||||
return (
|
||||
<div className='d-flex'>
|
||||
<div className='flex-1 p-2'>
|
||||
<span className='mission-header'>{title}</span>
|
||||
</div>
|
||||
<div className='flex-2 p-2'>
|
||||
<p className='mission-para'>{body}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const previousLeadershipLink =
|
||||
'https://docs.google.com/spreadsheets/d/1a3RYdqrDi1IPG9BKWQ2xhoX3YCPQKUl_FsRLvIVEMPg/edit?usp=drive_open&ouid=0';
|
||||
|
||||
|
@ -45,8 +33,8 @@ export default function Mission() {
|
|||
text={mission.quote_text}
|
||||
/>
|
||||
|
||||
<MissionParagraph title='Vision' body={mission.vision} />
|
||||
<MissionParagraph title='Mission' body={mission.mission} />
|
||||
<ParagraphWithHeader title='Vision' body={mission.vision} />
|
||||
<ParagraphWithHeader title='Mission' body={mission.mission} />
|
||||
|
||||
<Centered>
|
||||
<BlueButtonLink href={previousLeadershipLink}>
|
||||
|
|
|
@ -4,7 +4,7 @@ import Hero from '../components/Hero';
|
|||
import imageUrl from '../lib/imageUrl';
|
||||
import '../css/article.css';
|
||||
import useNewsArticle from '../hooks/useNewsArticle';
|
||||
import LocalLinkClickable from '../components/LocalLinkClickable';
|
||||
import ClickableLink from '../components/ClickableLink';
|
||||
import BlockContentWithExternalLinks from '../components/BlockContentWithExternalLinks';
|
||||
import PrimaryHeader from '../components/PrimaryHeader';
|
||||
|
||||
|
@ -18,7 +18,7 @@ export default function NewsArticle() {
|
|||
}
|
||||
|
||||
const goToAllNewsArticles = (
|
||||
<LocalLinkClickable to='/news'>Go to all news articles</LocalLinkClickable>
|
||||
<ClickableLink href='/news'>Go to all news articles</ClickableLink>
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -33,7 +33,7 @@ export default function NewsArticle() {
|
|||
Posted {article.publish_date} by {article.author || 'No author'}
|
||||
</i>
|
||||
<br />
|
||||
<div id='article-content' className='article-paragraphs'>
|
||||
<div className='article-paragraphs'>
|
||||
<BlockContentWithExternalLinks blocks={article.content} />
|
||||
</div>
|
||||
<br />
|
||||
|
|
|
@ -26,7 +26,6 @@ export default function Officers() {
|
|||
const officerList = officersSorted.map((officer) => (
|
||||
<MemberRow member={officer} />
|
||||
));
|
||||
console.log(officersSorted);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
Loading…
Reference in New Issue
Block a user