diff --git a/components/ArticleList.tsx b/components/ArticleList.tsx index 034d10a..4e0a833 100644 --- a/components/ArticleList.tsx +++ b/components/ArticleList.tsx @@ -1,4 +1,5 @@ import Link from 'next/link'; +import {Article} from "../lib/Schema" function generateRoute(slug: string) { return `/entry/${slug}`; @@ -17,10 +18,6 @@ function ArticleItem({ title, slug }: Article) { ); } -export type Article = { - title: string; - slug: string; -}; interface ArticleListProps { articles: Article[]; diff --git a/components/ChapterEntryBlock.tsx b/components/ChapterEntryBlock.tsx new file mode 100644 index 0000000..81ca3bb --- /dev/null +++ b/components/ChapterEntryBlock.tsx @@ -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 ( +
+
+
+ + +
+ ); +} diff --git a/components/ChapterEntryListView.tsx b/components/ChapterEntryListView.tsx new file mode 100644 index 0000000..544320e --- /dev/null +++ b/components/ChapterEntryListView.tsx @@ -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 ( + + + + {title} + + + +); +} + + interface ArticleListProps { + articles: Article[]; + } + + export default function ChapterEntryListView({ articles }: ArticleListProps) { + const items = articles.map((article) => ); + return ( +
+

Articles

+ + {items} +
+
+ ); + } diff --git a/data/test_chapters.json b/data/test_chapters.json new file mode 100644 index 0000000..8a99289 --- /dev/null +++ b/data/test_chapters.json @@ -0,0 +1,67 @@ +[ + { + "title": "Overview: Getting Started at UTD", + "slug": "get-started", + "authors": [ + { + "name": "Willie Chalmers III", + "email": "test@example.com" + } + ], + "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": "test@example.com" + } + ], + "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" + } + ] + \ No newline at end of file diff --git a/lib/Schema.ts b/lib/Schema.ts new file mode 100644 index 0000000..56705c4 --- /dev/null +++ b/lib/Schema.ts @@ -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; + }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b70d343..3d478a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9950,4 +9950,4 @@ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==" } } -} +} \ No newline at end of file diff --git a/pages/chapter/[chapterId].tsx b/pages/chapter/[chapterId].tsx new file mode 100644 index 0000000..cfb26eb --- /dev/null +++ b/pages/chapter/[chapterId].tsx @@ -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) { + return ( +
+ +
+ ); + } + + 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 { + 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 { + 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> { + const id = params?.chapterId as string; + const data = await getEntryData(id); + return { + props: { + chapter: data, + }, + }; + } + \ No newline at end of file diff --git a/pages/entry/[entryId].tsx b/pages/entry/[entryId].tsx index 14debe4..f1d0a22 100644 --- a/pages/entry/[entryId].tsx +++ b/pages/entry/[entryId].tsx @@ -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) { return ( @@ -23,10 +24,6 @@ export default function EntryPage({ entry }: InferGetStaticPropsType