Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Chapter View Page #86

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions components/ArticleList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Link from 'next/link';
import {Article} from "../lib/Schema"

function generateRoute(slug: string) {
return `/entry/${slug}`;
Expand All @@ -17,10 +18,6 @@ function ArticleItem({ title, slug }: Article) {
);
}

export type Article = {
title: string;
slug: string;
};

interface ArticleListProps {
articles: Article[];
Expand Down
37 changes: 37 additions & 0 deletions components/ChapterEntryBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { ContributorData } from './ContributorList';
import Header from './Header';
import ArticleList from './ArticleList';
import { Article } from '../lib/Schema';
import ChapterEntryListView from './ChapterEntryListView';
interface GuideChapterContentProps {
url: string;
date: number;
title: string;
contributors: ContributorData[];
entries: Article[];
content: string;
}

export default function GuideChapterContent({
url,
date,
title,
contributors,
entries,
content,
}: GuideChapterContentProps) {
return (
<div className="p-8 bg-white drop-shadow-[0_2px_2px_rgba(0,0,0,0.25)] max-w-4xl mx-auto rounded-md">
<Header
url={url}
date={new Date(date).toLocaleDateString()}
title={title}
contributors={contributors}
/>
<div className="mt-4 prose lg:prose-xl" dangerouslySetInnerHTML={{ __html: content }} />
<ChapterEntryListView articles={entries} />

</div>
);
}
39 changes: 39 additions & 0 deletions components/ChapterEntryListView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import Link from 'next/link';
import {Article} from "../lib/Schema"

function generateRoute(slug: string) {
return `/entry/${slug}`;
}


function ArticleItem({ title, slug }: Article) {
return (
<tr className="">
<th className='border border-solid border-black/[.40] text-left py-4 bg-white'>
<Link
href={generateRoute(slug)}
className="px-4 text-xl text-dark font-bold hover:text-primary-dark focus:text-primary-dark transition"
>
{title}
</Link>
</th>
</tr>
);
}

interface ArticleListProps {
articles: Article[];
}

export default function ChapterEntryListView({ articles }: ArticleListProps) {
const items = articles.map((article) => <ArticleItem key={article.slug} {...article} />);
return (
<div className = "mx-0 my-6 px-0 pb-4 bg-[#E2E7FF] rounded-2xl border border-solid border-black">
<h2 className='px-5 py-4 text-2xl font-semibold'>Articles</h2>
<table className='table-auto mx-auto my-auto w-full pb-8'>
{items}
</table>
</div>
);
}
67 changes: 67 additions & 0 deletions data/test_chapters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
[
{
"title": "Overview: Getting Started at UTD",
"slug": "get-started",
"authors": [
{
"name": "Willie Chalmers III",
"email": "[email protected]"
}
],
"chapterEntries": [
{
"title": "How to Survive and Thrive at UTD.",
"slug": "introduction"
},
{
"title": "How to get involved with student life.",
"slug": "get-involved"
},
{
"title": "Building Relationships with Professor.",
"slug": "contacting-professors"
},
{
"title": "Getting an Internship.",
"slug": "get-internship"
},
{
"title": "How to get involved with student life",
"slug": "get-involved-2"
},
{
"title": "Building Relationships with Professor",
"slug": "contacting-professors-2"
}
],
"content": "Getting started as a Freshman can be challenging and overwhelming. To help you find your way, we have curated a list of articles to help you get started on your academic journey.",
"lastUpdated": "2023-02-23T20:40"
},
{
"title": "This is a test chapter.",
"slug": "test",
"authors": [
{
"name": "Willie Chalmers III",
"email": "[email protected]"
}
],
"chapterEntries": [
{
"title": "This is a test entry under chapter.",
"slug": "test"
},
{
"title": "This is 2nd test entry under chapter.",
"slug": "get-involved"
},
{
"title": "This is 3rd test entry under chapter.",
"slug": "get-involved"
}
],
"content": "# Getting started as a Freshman can be challenging and overwhelming. To help you find your way, we have curated a list of articles to help you get started on your academic journey.",
"lastUpdated": "2023-02-23T20:40"
}
]

20 changes: 20 additions & 0 deletions lib/Schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export type Author = {
name: string;
email: string;
};

export type Article = {
title: string;
slug: string;
};

export type GuideEntry = {
slug: string;
title: string;
authors: Author[];
content: string;
/**
* UNIX timestamp in milliseconds of when this entry was last updated.
*/
lastUpdated: number;
};
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 100 additions & 0 deletions pages/chapter/[chapterId].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type {
GetStaticPathsResult,
GetStaticPropsContext,
GetStaticPropsResult,
InferGetStaticPropsType,
} from 'next/types';
import { remark } from 'remark';
import html from 'remark-html';
import GuideChapterBlock from '../../components/ChapterEntryBlock';
import testChapters from '../../data/test_chapters.json';
import {Article, Author} from "../../lib/Schema"

export default function EntryPage({ chapter }: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<div className="py-8 bg-[#e0ecfb] min-h-screen">
<GuideChapterBlock
url={''}
date={chapter.lastUpdated}
title={chapter.title}
contributors={chapter.authors}
entries = {chapter.chapterEntries}
content={chapter.content}
/>
</div>
);
}

type GuideChapter = {
slug: string;
title: string;
authors: Author[];
chapterEntries: Article[];
content: string;
/**
* UNIX timestamp in milliseconds of when this entry was last updated.
*/
lastUpdated: number;
};

type ChapterPageProps = {
chapter: GuideChapter;
};

/**
* Fetches data for one Guide entry page.
*
* @param id
* @returns Guide entry data
*/
async function getEntryData(id: string): Promise<GuideChapter> {
const chapter = testChapters.find((chapter) => chapter.slug === id);
console.log(chapter);
if (chapter) {
const data = {
...chapter,
lastUpdated: new Date(chapter.lastUpdated).valueOf(),
content: (await remark().use(html).process(chapter.content)).toString(),
};
return data;
} else {
throw new Error('Invalid entry ID provided.');
}
}

/**
* Returns all valid entryId params.
*
* Functionally, this gets all possible entry IDs so Next.js has all the valid
* routes used to check the validity of the requested URL on each request.
*/
export async function getStaticPaths(): Promise<GetStaticPathsResult> {
return {
paths: testChapters.map(({ slug }) => {
return {
params: {
chapterId: slug,
},
};
}),
fallback: false,
};
}

/**
* Fetches entry data.
*
* At build time, this gets the data for a Guide entry from our data source.
*/
export async function getStaticProps({
params,
}: GetStaticPropsContext): Promise<GetStaticPropsResult<ChapterPageProps>> {
const id = params?.chapterId as string;
const data = await getEntryData(id);
return {
props: {
chapter: data,
},
};
}

5 changes: 1 addition & 4 deletions pages/entry/[entryId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { remark } from 'remark';
import html from 'remark-html';
import GuideEntryBlock from '../../components/GuideEntryBlock';
import testEntries from '../../data/test_entries.json';
import {Author} from "../../lib/Schema"

export default function EntryPage({ entry }: InferGetStaticPropsType<typeof getStaticProps>) {
return (
Expand All @@ -23,10 +24,6 @@ export default function EntryPage({ entry }: InferGetStaticPropsType<typeof getS
);
}

type Author = {
name: string;
email: string;
};

type GuideEntry = {
slug: string;
Expand Down
4 changes: 3 additions & 1 deletion pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { GetStaticPropsResult, InferGetStaticPropsType } from 'next';
import Head from 'next/head';
import Link from 'next/link';
import ArticleList, { Article } from '../components/ArticleList';
import ArticleList from '../components/ArticleList';
import {Article} from "../lib/Schema"

import SiteFooter from '../components/SiteFooter';
import test_entries from '../data/test_entries.json';

Expand Down