diff --git a/src/app/learn/LearnContent.tsx b/src/app/learn/LearnContent.tsx new file mode 100644 index 000000000..7a7157100 --- /dev/null +++ b/src/app/learn/LearnContent.tsx @@ -0,0 +1,90 @@ +'use client' + +import Link from 'next/link' +import { useSearchParams } from 'next/navigation' + +import { learnLevels, LearnLevelType, LearnContentType } from './constants' + +const LearnItem = ({ + index, + id, + content +}: { + index: number + id: string + content: LearnContentType +}) => { + return ( +
+ + +

+ {index}. {content.label} +

+
+ +
+ ) +} + +const LearnList = ({ level }: { level: LearnLevelType }) => { + return ( +
+
+

{level.label}

+
+ {level.sections.map(section => { + return ( +
+ {/* Section header */} +

{section.label}

+ + {/* Section items */} + {true && ( +
    + {section.content.map((content, idx) => ( +
  • + +
  • + ))} +
+ )} +
+ ) + })} +
+
+
+ ) +} + +export const LearnContent = () => { + const searchParams = useSearchParams() + const level = searchParams.get('level') + + return ( +
+
+ {learnLevels.map(learnLevel => { + return !level || level == learnLevel.value ? ( + + ) : ( + <> + ) + })} +
+
+ ) +} diff --git a/src/app/learn/LearnSidebar.tsx b/src/app/learn/LearnSidebar.tsx new file mode 100644 index 000000000..bcd5cf511 --- /dev/null +++ b/src/app/learn/LearnSidebar.tsx @@ -0,0 +1,52 @@ +'use client' + +import Link from 'next/link' +import { useSearchParams } from 'next/navigation' + +import clsx from 'clsx' + +import { learnSidebarSelects } from './constants' + +export const LearnSidebar = () => { + const searchParams = useSearchParams() + + const level = searchParams.get('level') + + return ( +
+
+
+ {learnSidebarSelects.map(learnLevelSelect => { + return ( + +

+ {learnLevelSelect.label} +

+ + ) + })} +
+
+
+ ) +} diff --git a/src/app/learn/constants.ts b/src/app/learn/constants.ts new file mode 100644 index 000000000..6c7f09c04 --- /dev/null +++ b/src/app/learn/constants.ts @@ -0,0 +1,231 @@ +export type LearnContentType = { + label: string + value: string +} + +export type LearnSectionType = { + label: string + value: string + content: LearnContentType[] +} + +export type LearnLevelType = { + label: string + value: string + sections: LearnSectionType[] +} + +export const learnLevels: LearnLevelType[] = [ + { + label: 'เตรียมตัวก่อนเข้าค่าย', + value: 'pre-posn', + sections: [ + { + label: 'คณิตศาสตร์', + value: 'math', + content: [ + { + label: 'บทนำ', + value: 'intro' + }, + { + label: 'จำนวน ระบบจำนวน การดำเนินการของจำนวน', + value: 'number-operation' + }, + { + label: 'ความสัมพันธ์ ฟังก์ชัน', + value: 'function-relation' + }, + { + label: 'สมการ และ อสมการ', + value: 'equation-inequality' + }, + { + label: 'เซต และ ตรรกศาสตร์', + value: 'logic-set' + }, + { + label: 'การวัดและเรขาคณิต', + value: 'geometry' + }, + { + label: 'สถิติและความน่าจะเป็น', + value: 'prob-stats' + } + ] + }, + { + label: 'กระบวนการคิด', + value: 'problem-solving', + content: [ + { + label: 'กระบวนการแก้ปัญหาที่มีการใช้ตรรกะ และฟังก์ชัน', + value: 'problem-solving' + } + ] + } + ] + }, + { + label: 'ค่ายสอวน. 1', + value: 'posn', + sections: [ + { + label: 'คณิตศาสตร์', + value: 'math', + content: [ + { + label: 'ทฤษฎีตัวเลข เมทริกซ์', + value: 'matrix' + }, + { + label: 'ลำดับและอนุกรม', + value: 'sequence-series' + }, + { + label: 'เลขฐาน', + value: 'radix' + } + ] + }, + { + label: 'การเขียนโปรแกรม', + value: 'programming', + content: [ + { + label: 'ทำไมถึงใช้ C++', + value: 'why-cpp' + }, + { + label: 'การติดตั้งโปรแกรม', + value: 'installation' + }, + { + label: 'พื้นฐานภาษา C และ C++', + value: 'cpp-basic' + } + ] + } + ] + }, + { + label: 'ค่ายสอวน. 2 และระดับชาติ', + value: 'toi', + sections: [ + { + label: 'คณิตศาสตร์', + value: 'math', + content: [ + { + label: 'เวกเตอร์และระบบพิกัดคาร์ทีเซียน', + value: 'vector-cartesian' + }, + { + label: 'การนับ', + value: 'counting' + }, + { + label: 'ทฤษฎีกราฟ', + value: 'graph' + } + ] + }, + { + label: 'Data Structure', + value: 'datastructure', + content: [ + { + label: 'Intro To DS', + value: 'intro' + }, + { + label: 'Primitive', + value: 'primitive' + }, + { + label: 'Array and Vector', + value: 'array-vector' + }, + { + label: 'string', + value: 'string' + }, + { + label: 'pair', + value: 'pair' + }, + { + label: 'stack and queue', + value: 'stack-queue' + }, + { + label: 'priority queue', + value: 'priority-queue' + }, + { + label: 'set and map', + value: 'set-map' + }, + { + label: 'choosing datastructure', + value: 'choosing-ds' + } + ] + }, + { + label: 'Algorithm', + value: 'algorithm', + content: [ + { + label: 'intro', + value: 'intro' + }, + { + label: 'bruteforce', + value: 'bruteforce' + } + ] + } + ] + }, + { + label: 'สสวท.', + value: 'ipst', + sections: [ + { + label: 'คณิตศาสตร์', + value: 'math', + content: [ + { + label: 'คณิตศาสตร์ระดับสูง', + value: 'advanced-math' + } + ] + } + ] + }, + { + label: 'IOI', + value: 'ioi', + sections: [ + { + label: 'คณิตศาสตร์', + value: 'math', + content: [ + { + label: 'คณิตศาสตร์ระดับสูง', + value: 'advanced-math' + } + ] + } + ] + } +] + +export const learnSidebarSelects = [ + { + label: 'Overview', + value: 'overview' + }, + ...learnLevels.map(({ label, value }) => ({ label, value })) +] diff --git a/src/app/learn/content/[...id]/RenderContent.tsx b/src/app/learn/content/[...id]/RenderContent.tsx new file mode 100644 index 000000000..3fc54f26f --- /dev/null +++ b/src/app/learn/content/[...id]/RenderContent.tsx @@ -0,0 +1,37 @@ +'use client' + +import { ExclamationCircleIcon } from '@heroicons/react/24/solid' +import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote' + +import components from '@/components/common/MDXComponents' + +const RenderUnderConstruction = () => { + return ( +
+ + +

+ เนื้อหาส่วนนี้ยังไม่สมบูรณ์ +

+

ขออภัยในความไม่สะดวก

+
+ ) +} + +export const RenderContent = ({ + content_md +}: { + content_md: MDXRemoteSerializeResult | null +}) => { + if (!content_md) return + + return ( +
+
+
+ +
+
+
+ ) +} diff --git a/src/app/learn/content/[...id]/page.tsx b/src/app/learn/content/[...id]/page.tsx new file mode 100644 index 000000000..0d3824bfb --- /dev/null +++ b/src/app/learn/content/[...id]/page.tsx @@ -0,0 +1,58 @@ +import { Suspense } from 'react' + +import Link from 'next/link' + +import { ArrowLeftIcon } from '@heroicons/react/24/solid' + +import { getLearnMaterial } from '@/lib/api/queries/getLearnMaterial' + +import { RenderContent } from './RenderContent' +import { learnLevels } from '../../constants' + +const ContentSidebar = ({ id }: { id: string }) => { + const path = id.split('_') + if (path.length != 3) return <> + const levelLabel = learnLevels.filter(lev => lev.value == path[0])[0].label + const label = learnLevels + .filter(lev => lev.value == path[0])[0] + .sections.filter(sec => sec.value == path[1])[0] + .content.filter(con => con.value == path[2])[0].label + + return ( +
+
+
+ + + + + exit + + + +

เนื้อหา{levelLabel}

+

เรื่อง {label}

+
+
+
+ ) +} + +const Page = async ({ params }: { params: { id: string[] } }) => { + const learnMaterial = await getLearnMaterial(params.id[0]) + return ( +
+
+
+
+ + + + +
+
+
+ ) +} + +export default Page diff --git a/src/app/learn/page.tsx b/src/app/learn/page.tsx index 1d5ca449f..73d323500 100644 --- a/src/app/learn/page.tsx +++ b/src/app/learn/page.tsx @@ -1,6 +1,9 @@ +import { Suspense } from 'react' + import { Metadata, type NextPage } from 'next' -import Link from 'next/link' +import { LearnContent } from './LearnContent' +import { LearnSidebar } from './LearnSidebar' export const metadata: Metadata = { title: 'Learn | programming.in.th' @@ -8,14 +11,24 @@ export const metadata: Metadata = { const Learn: NextPage = () => { return ( -
-

- Coming Soon... -

- - กลับหน้าหลัก - -
+
+
+
+

+ Learn +

+

+ Learn with programing.in.th +

+
+
+ + + + +
+
+
) } diff --git a/src/lib/api/queries/getLearnMaterial.ts b/src/lib/api/queries/getLearnMaterial.ts new file mode 100644 index 000000000..1c047a0cd --- /dev/null +++ b/src/lib/api/queries/getLearnMaterial.ts @@ -0,0 +1,34 @@ +import 'server-only' + +import { notFound } from 'next/navigation' + +import { MDXRemoteSerializeResult } from 'next-mdx-remote' + +import { mdxToHtml } from '@/lib/renderMarkdown' + +/** + * Get learn material (md file), only used in server components + * + * @throws 404 Error + */ +export async function getLearnMaterial( + id: string +): Promise { + if (!id) return notFound() + + let solution = null + + try { + const solutionRes = await fetch( + `${process.env.NEXT_PUBLIC_AWS_URL}/tutorial/${id.replaceAll('_', '/')}.md` + ) + + if (solutionRes.status === 200) { + const raw = await solutionRes.text() + solution = await mdxToHtml(raw) + } + } catch (error) { + console.log(error) + } + return solution +}