From 13c4a03878ace72f0665a1dc3028bab4a5363187 Mon Sep 17 00:00:00 2001 From: MarkMelior Date: Fri, 12 Jul 2024 18:24:18 +0300 Subject: [PATCH] update mdx --- app/layout.tsx | 4 +- app/projects/[category]/[name]/page.tsx | 41 ++++++++ app/projects/[category]/page.tsx | 33 +++++++ app/projects/[name]/page.tsx | 25 ----- next.config.mjs | 1 - package.json | 3 +- projects/app-router-auth/page.mdx | 20 ---- .../app-router-auth/examples/auth.tsx | 0 .../app-router-auth/examples/codes.ts | 0 .../app-router-auth/examples/services/data.ts | 0 .../examples/services/definitions.ts | 0 .../examples/services/login.ts | 0 .../app-router-auth/examples/services/user.ts | 0 .../examples/ui/form-login.tsx | 0 .../best-practice/app-router-auth/page.mdx | 48 +++++++++ projects/best-practice/index.mdx | 3 + src/entity/project/index.ts | 9 +- .../model/services/get-project-data.ts | 34 ------- .../project/model/services/get-project.ts | 43 ++++++++ .../services/get-projects-by-category.ts | 26 +++++ .../model/services/get-projects-data.ts | 24 ----- .../project/model/services/get-projects.ts | 25 +++++ src/mdx-components.tsx | 22 ++--- .../hooks/useMessage/useMessage.module.scss | 2 +- src/shared/types/programming-language.ts | 5 - src/shared/ui/code-block/code-block.tsx | 95 +++++++----------- src/shared/ui/code-block/code.tsx | 48 +++++++++ src/shared/ui/code/code.tsx | 54 ---------- src/shared/ui/index.ts | 2 +- .../ui/sidebar-navigation/model/data.tsx | 30 +++--- src/shared/ui/stack-buttons/model/data.tsx | 5 + src/shared/ui/text/text.tsx | 57 ++++++----- src/widgets/footer/footer.tsx | 99 ++----------------- src/widgets/footer/navigation-button.tsx | 90 +++++++++++++++++ src/widgets/light/light.tsx | 2 +- 35 files changed, 472 insertions(+), 378 deletions(-) create mode 100644 app/projects/[category]/[name]/page.tsx create mode 100644 app/projects/[category]/page.tsx delete mode 100644 app/projects/[name]/page.tsx delete mode 100644 projects/app-router-auth/page.mdx rename projects/{ => best-practice}/app-router-auth/examples/auth.tsx (100%) rename projects/{ => best-practice}/app-router-auth/examples/codes.ts (100%) rename projects/{ => best-practice}/app-router-auth/examples/services/data.ts (100%) rename projects/{ => best-practice}/app-router-auth/examples/services/definitions.ts (100%) rename projects/{ => best-practice}/app-router-auth/examples/services/login.ts (100%) rename projects/{ => best-practice}/app-router-auth/examples/services/user.ts (100%) rename projects/{ => best-practice}/app-router-auth/examples/ui/form-login.tsx (100%) create mode 100644 projects/best-practice/app-router-auth/page.mdx create mode 100644 projects/best-practice/index.mdx delete mode 100644 src/entity/project/model/services/get-project-data.ts create mode 100644 src/entity/project/model/services/get-project.ts create mode 100644 src/entity/project/model/services/get-projects-by-category.ts delete mode 100644 src/entity/project/model/services/get-projects-data.ts create mode 100644 src/entity/project/model/services/get-projects.ts delete mode 100644 src/shared/types/programming-language.ts create mode 100644 src/shared/ui/code-block/code.tsx delete mode 100644 src/shared/ui/code/code.tsx create mode 100644 src/widgets/footer/navigation-button.tsx diff --git a/app/layout.tsx b/app/layout.tsx index 78f7b40..cacaff8 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -9,8 +9,8 @@ import { Suspense } from 'react'; const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { - title: 'Simple App: Mark Melior', - description: 'Generated by create next app', + title: 'Simple App | Mark Melior', + description: `Small and modern pet-projects. Hi, I'am Mark Melior - Frontend developer.`, }; export default function RootLayout({ diff --git a/app/projects/[category]/[name]/page.tsx b/app/projects/[category]/[name]/page.tsx new file mode 100644 index 0000000..4c5fa85 --- /dev/null +++ b/app/projects/[category]/[name]/page.tsx @@ -0,0 +1,41 @@ +import { getProject } from '@/entity/project'; +import { Header } from '@/widgets'; +import { Metadata } from 'next'; +import dynamic from 'next/dynamic'; + +export type ProjectPageProps = { + params: { name: string; category: string }; +}; + +export default async function ProjectPage({ params }: ProjectPageProps) { + const Project = dynamic( + () => import(`/projects/${params.category}/${params.name}/page.mdx`), + ); + + const { metadata } = await getProject(params.category, params.name); + + return ( + <> +
+ + + ); +} + +export async function generateMetadata({ + params, +}: ProjectPageProps): Promise { + const { metadata } = await getProject(params.category, params.name); + + return { + title: `Simple App | ${metadata.title}`, + description: `${metadata.description}. Technologies: ${metadata.tags?.join( + ', ', + )}`, + }; +} diff --git a/app/projects/[category]/page.tsx b/app/projects/[category]/page.tsx new file mode 100644 index 0000000..efb1648 --- /dev/null +++ b/app/projects/[category]/page.tsx @@ -0,0 +1,33 @@ +import { getProjectsByCategory } from '@/entity/project'; + +export type ProjectCategoryPageProps = { + params: { category: string }; +}; + +export default async function ProjectCategoryPage({ + params, +}: ProjectCategoryPageProps) { + const projects = await getProjectsByCategory(params.category); + + return ( + <> + {projects.map(({ title }) => ( + <> + ))} + + ); +} + +// todo +// export async function generateMetadata({ +// params, +// }: ProjectCategoryPageProps): Promise { +// const { metadata } = await getProject(params.category, params.name); + +// return { +// title: `Simple App | ${metadata.title}`, +// description: `${metadata.description}. Technologies: ${metadata.tags?.join( +// ', ', +// )}`, +// }; +// } diff --git a/app/projects/[name]/page.tsx b/app/projects/[name]/page.tsx deleted file mode 100644 index f36f9e0..0000000 --- a/app/projects/[name]/page.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { getProjectData } from '@/entity/project'; -import { Header } from '@/widgets'; -import dynamic from 'next/dynamic'; - -export type ProjectPageProps = { - params: { name: string }; -}; - -export default async function ProjectPage({ params }: ProjectPageProps) { - const Project = dynamic(() => import(`/projects/${params.name}/page.mdx`)); - - const metadata = await getProjectData(params.name); - - return ( - <> -
- - - ); -} diff --git a/next.config.mjs b/next.config.mjs index cbf7cc1..90952ff 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -4,7 +4,6 @@ import remarkGfm from 'remark-gfm'; /** @type {import('next').NextConfig} */ const nextConfig = { pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'], - transpilePackages: ['next-mdx-remote'], }; const withMDX = createMDX({ diff --git a/package.json b/package.json index 8680bba..552387e 100644 --- a/package.json +++ b/package.json @@ -15,14 +15,12 @@ "@next/mdx": "^14.2.5", "@nextui-org/react": "^2.4.2", "@prisma/client": "^5.16.1", - "@types/mdx": "^2.0.13", "bcryptjs": "^2.4.3", "clsx": "^2.1.1", "framer-motion": "^11.2.13", "gray-matter": "^4.0.3", "jose": "^5.6.3", "next": "14.2.4", - "next-mdx-remote": "^5.0.0", "next-themes": "^0.3.0", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -36,6 +34,7 @@ "devDependencies": { "@tailwindcss/typography": "^0.5.13", "@types/bcryptjs": "^2.4.6", + "@types/mdx": "^2.0.13", "@types/node": "^20.14.10", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", diff --git a/projects/app-router-auth/page.mdx b/projects/app-router-auth/page.mdx deleted file mode 100644 index 0a12b92..0000000 --- a/projects/app-router-auth/page.mdx +++ /dev/null @@ -1,20 +0,0 @@ -import { AuthExample } from './examples/auth'; - -export const metadata = { - note: 'Auth', - title: 'Next.js: Authentication', - description: 'Best practices for Server Components, Actions, Middleware', - tags: ['TypeScript', 'Cookie', 'SSR', 'Prisma'], -}; - - - -## About this approach - -Getting user data: `const user = await getUser();`. It's very simple :) - -test)) - -```typescript filename="TypeScript" -const user = await getUser(); -``` diff --git a/projects/app-router-auth/examples/auth.tsx b/projects/best-practice/app-router-auth/examples/auth.tsx similarity index 100% rename from projects/app-router-auth/examples/auth.tsx rename to projects/best-practice/app-router-auth/examples/auth.tsx diff --git a/projects/app-router-auth/examples/codes.ts b/projects/best-practice/app-router-auth/examples/codes.ts similarity index 100% rename from projects/app-router-auth/examples/codes.ts rename to projects/best-practice/app-router-auth/examples/codes.ts diff --git a/projects/app-router-auth/examples/services/data.ts b/projects/best-practice/app-router-auth/examples/services/data.ts similarity index 100% rename from projects/app-router-auth/examples/services/data.ts rename to projects/best-practice/app-router-auth/examples/services/data.ts diff --git a/projects/app-router-auth/examples/services/definitions.ts b/projects/best-practice/app-router-auth/examples/services/definitions.ts similarity index 100% rename from projects/app-router-auth/examples/services/definitions.ts rename to projects/best-practice/app-router-auth/examples/services/definitions.ts diff --git a/projects/app-router-auth/examples/services/login.ts b/projects/best-practice/app-router-auth/examples/services/login.ts similarity index 100% rename from projects/app-router-auth/examples/services/login.ts rename to projects/best-practice/app-router-auth/examples/services/login.ts diff --git a/projects/app-router-auth/examples/services/user.ts b/projects/best-practice/app-router-auth/examples/services/user.ts similarity index 100% rename from projects/app-router-auth/examples/services/user.ts rename to projects/best-practice/app-router-auth/examples/services/user.ts diff --git a/projects/app-router-auth/examples/ui/form-login.tsx b/projects/best-practice/app-router-auth/examples/ui/form-login.tsx similarity index 100% rename from projects/app-router-auth/examples/ui/form-login.tsx rename to projects/best-practice/app-router-auth/examples/ui/form-login.tsx diff --git a/projects/best-practice/app-router-auth/page.mdx b/projects/best-practice/app-router-auth/page.mdx new file mode 100644 index 0000000..eb1b764 --- /dev/null +++ b/projects/best-practice/app-router-auth/page.mdx @@ -0,0 +1,48 @@ +import { AuthExample } from './examples/auth'; + +export const metadata = { + note: 'Auth', + title: 'Next.js: Authentication', + description: 'Best practices for Server Components, Actions, Middleware', + tags: ['TypeScript', 'Cookie', 'SSR', 'Prisma'], +}; + + + +## About this approach + +Getting user data: `const user = await getUser();`. It's very simple :) + +- hi +- man `test` good! +- i'm good + +test)) + +```TypeScript filename="src/features/auth/api/jwt.ts" +import { SignJWT, jwtVerify } from 'jose'; +import { SessionPayload } from '../types/definitions'; + +const secretKey = process.env.SESSION_SECRET; +const encodedKey = new TextEncoder().encode(secretKey); + +export async function encrypt(payload: SessionPayload) { + return new SignJWT(payload) + .setProtectedHeader({ alg: 'HS256' }) + .setIssuedAt() + .setExpirationTime('7d') + .sign(encodedKey); +} + +export async function decrypt(session: string | undefined = '') { + try { + const { payload } = await jwtVerify(session, encodedKey, { + algorithms: ['HS256'], + }); + return payload; + } catch (error) { + // console.log('Failed to verify session'); + return null; + } +} +``` diff --git a/projects/best-practice/index.mdx b/projects/best-practice/index.mdx new file mode 100644 index 0000000..64008cc --- /dev/null +++ b/projects/best-practice/index.mdx @@ -0,0 +1,3 @@ +export const metadata = { + title: 'Best Practice', +}; diff --git a/src/entity/project/index.ts b/src/entity/project/index.ts index 8578974..46501a1 100644 --- a/src/entity/project/index.ts +++ b/src/entity/project/index.ts @@ -1,5 +1,6 @@ -import { getProjectData, ProjectData } from './model/services/get-project-data'; -import { getProjectsData } from './model/services/get-projects-data'; +import { getProject, Project } from './model/services/get-project'; +import { getProjects } from './model/services/get-projects'; +import { getProjectsByCategory } from './model/services/get-projects-by-category'; -export { getProjectData, getProjectsData }; -export type { ProjectData }; +export { getProject, getProjects, getProjectsByCategory }; +export type { Project }; diff --git a/src/entity/project/model/services/get-project-data.ts b/src/entity/project/model/services/get-project-data.ts deleted file mode 100644 index 809f963..0000000 --- a/src/entity/project/model/services/get-project-data.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { StackVariants } from '@/shared/ui'; - -export interface ProjectData { - id: string; - note: string; - title: string; - description: string; - tags?: StackVariants[]; -} - -export async function getProjectData(name: string): Promise { - //Lazy load the mdx file for the project - try { - const file = (await import(`/projects/${name}/page.mdx`)) as Partial<{ - metadata: ProjectData; - }>; - - if (file?.metadata) { - return { ...file.metadata, id: file.metadata.title }; - } else { - throw new Error(`Unable to find metadata in file ${name}.mdx`); - } - } catch (error: any) { - console.log(error?.message); - - return { - id: '', - note: '', - title: '', - description: '', - tags: [], - }; - } -} diff --git a/src/entity/project/model/services/get-project.ts b/src/entity/project/model/services/get-project.ts new file mode 100644 index 0000000..58b4a25 --- /dev/null +++ b/src/entity/project/model/services/get-project.ts @@ -0,0 +1,43 @@ +import { StackVariants } from '@/shared/ui'; +import fs from 'fs'; +import matter from 'gray-matter'; +import path from 'path'; + +export interface ProjectMetadata { + note: string; + title: string; + description: string; + tags?: StackVariants[]; + publishDate: string; +} + +export interface Project { + metadata: ProjectMetadata; + content: string; +} + +export async function getProject( + category: string, + name: string, +): Promise { + const { metadata: exportedMetadata } = (await import( + `/projects/${category}/${name}/page.mdx` + )) as Partial<{ + metadata: ProjectMetadata; + }>; + + const dir = path.join(process.cwd(), 'projects', category, name, 'page.mdx'); + const mdxFile = fs.readFileSync(dir); + const matterData = matter(mdxFile); + const matterMetadata = matterData.data as ProjectMetadata; + + if (!exportedMetadata && !matterMetadata) + throw new Error( + `Unable to find metadata in file /projects/${name}/page.mdx`, + ); + + return { + metadata: exportedMetadata || matterMetadata, + content: matterData.content, + }; +} diff --git a/src/entity/project/model/services/get-projects-by-category.ts b/src/entity/project/model/services/get-projects-by-category.ts new file mode 100644 index 0000000..d2183f3 --- /dev/null +++ b/src/entity/project/model/services/get-projects-by-category.ts @@ -0,0 +1,26 @@ +import { readdir } from 'fs/promises'; +import path from 'path'; +import { getProject, ProjectMetadata } from './get-project'; + +export async function getProjectsByCategory( + category: string, +): Promise { + // Retrieve slugs from post routes + const dir = path.join(process.cwd(), 'projects'); + const slugs = (await readdir(dir, { withFileTypes: true })).filter((dirent) => + dirent.isDirectory(), + ); + + // Retrieve metadata from MDX files + const posts = await Promise.all( + slugs.map(async ({ name }) => { + const { metadata } = await getProject(category, name); + return { slug: name, ...metadata }; + }), + ); + + // Sort posts from newest to oldest + posts.sort((a, b) => +new Date(b.publishDate) - +new Date(a.publishDate)); + + return posts; +} diff --git a/src/entity/project/model/services/get-projects-data.ts b/src/entity/project/model/services/get-projects-data.ts deleted file mode 100644 index f5963e4..0000000 --- a/src/entity/project/model/services/get-projects-data.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { readdirSync } from 'fs'; -import path from 'path'; -import { getProjectData, ProjectData } from './get-project-data'; - -export async function getProjectsData(): Promise { - try { - //Read the /blog folder at root dir - const projectsDir = path.resolve(process.cwd(), 'projects'); - const fileList: string[] = readdirSync(projectsDir); - - //Load each file - if (fileList.length > 0) { - const result = fileList.map(async (file) => { - //Remove extension to get blogId - const filename = file.substring(0, file.lastIndexOf('.')) || file; - - return await getProjectData(filename); - }); - - return Promise.all(result); - } - } catch (error) {} - return []; -} diff --git a/src/entity/project/model/services/get-projects.ts b/src/entity/project/model/services/get-projects.ts new file mode 100644 index 0000000..07cb71c --- /dev/null +++ b/src/entity/project/model/services/get-projects.ts @@ -0,0 +1,25 @@ +import { readdir } from 'fs/promises'; +import path from 'path'; +import { getProject, ProjectMetadata } from './get-project'; + +export async function getProjects(): Promise { + // Retrieve slugs from post routes + const dir = path.join(process.cwd(), 'projects'); + const slugs = (await readdir(dir, { withFileTypes: true })).filter((dirent) => + dirent.isDirectory(), + ); + + // Retrieve metadata from MDX files + const posts = await Promise.all( + slugs.map(async ({ name }) => { + // @ts-ignore // TODO: fix this + const { metadata } = await getProject(category, name); + return { slug: name, ...metadata }; + }), + ); + + // Sort posts from newest to oldest + posts.sort((a, b) => +new Date(b.publishDate) - +new Date(a.publishDate)); + + return posts; +} diff --git a/src/mdx-components.tsx b/src/mdx-components.tsx index a61fc0e..3f4149c 100644 --- a/src/mdx-components.tsx +++ b/src/mdx-components.tsx @@ -1,4 +1,4 @@ -import { Code, CodeBlock, Text } from '@/shared/ui'; +import { Code, CodeBlock, StackVariants, Text } from '@/shared/ui'; import type { MDXComponents } from 'mdx/types'; export function useMDXComponents(components: MDXComponents): MDXComponents { @@ -12,19 +12,17 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { } return ( - + ); }, - h2: (props) => { - return ( - - {props.children} - - ); - }, - p: (props) => { - return {props.children}; - }, + h2: Text.h2, + p: Text.p, + hr: Text.hr, + ul: Text.ul, ...components, }; } diff --git a/src/shared/hooks/useMessage/useMessage.module.scss b/src/shared/hooks/useMessage/useMessage.module.scss index 81359d3..0314423 100644 --- a/src/shared/hooks/useMessage/useMessage.module.scss +++ b/src/shared/hooks/useMessage/useMessage.module.scss @@ -110,7 +110,7 @@ } 100% { - margin-top: -50%; + margin-top: -52px; opacity: 0; } } \ No newline at end of file diff --git a/src/shared/types/programming-language.ts b/src/shared/types/programming-language.ts deleted file mode 100644 index 3e371e8..0000000 --- a/src/shared/types/programming-language.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type ProgrammingLanguage = - | 'TypeScript' - | 'JavaScript' - | 'Markdown' - | 'Prisma'; diff --git a/src/shared/ui/code-block/code-block.tsx b/src/shared/ui/code-block/code-block.tsx index bdf4147..1fa3373 100644 --- a/src/shared/ui/code-block/code-block.tsx +++ b/src/shared/ui/code-block/code-block.tsx @@ -2,15 +2,11 @@ import { cn, gitHubRepoLink } from '@/shared/lib'; import { GitHubPath } from '@/shared/types/github-path'; -import { ProgrammingLanguage } from '@/shared/types/programming-language'; import { Theme } from '@/shared/types/theme'; -import { Button, Link, Skeleton, Tooltip } from '@nextui-org/react'; +import { Button, Link, Tooltip } from '@nextui-org/react'; import { useTheme } from 'next-themes'; -import { FC, useEffect, useMemo, useState } from 'react'; -import { BiLogoJavascript, BiLogoTypescript } from 'react-icons/bi'; +import { FC, useEffect, useState } from 'react'; import { LuEye } from 'react-icons/lu'; -import { PiMarkdownLogo } from 'react-icons/pi'; -import { SiPrisma } from 'react-icons/si'; import { TbFileUnknown } from 'react-icons/tb'; import SyntaxHighlighter from 'react-syntax-highlighter'; import { @@ -18,12 +14,13 @@ import { atomOneLight, } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; import { CopyButton } from '../copy-button/copy-button'; +import { StackButtonData, StackVariants } from '../stack-buttons/model/data'; import './code-block.scss'; interface CodeBlockProps { text: string; fileName?: string; - language?: ProgrammingLanguage; + language?: StackVariants; linesLength?: number; github?: GitHubPath; className?: string; @@ -52,29 +49,6 @@ export const CodeBlock: FC = ({ setMounted(true); }, []); - const renderIcon = useMemo(() => { - switch (language) { - case 'TypeScript': - return ; - case 'JavaScript': - return ; - case 'Markdown': - return ; - case 'Prisma': - return ; - default: - return ; - } - }, [language]); - - if (!mounted) { - return ( - - ); - } - return (
= ({ className, )} > - {showHeader || - (fileName && ( -
- {renderIcon} - {fileName ? fileName : language} -
- {github?.path && ( - - - - )} - -
-
- ))} +
+ {StackButtonData[language]?.icon || } + {fileName ? fileName : language} +
+ {github?.path && ( + + + + )} + +
+
{isExpanded || !isLong ? text : lines.slice(0, linesLength).join('\n')} diff --git a/src/shared/ui/code-block/code.tsx b/src/shared/ui/code-block/code.tsx new file mode 100644 index 0000000..40fc81f --- /dev/null +++ b/src/shared/ui/code-block/code.tsx @@ -0,0 +1,48 @@ +'use client'; + +import { useCopy } from '@/shared/hooks'; +import { Button, Tooltip } from '@nextui-org/react'; +import { FC } from 'react'; +import { StackVariants } from '../stack-buttons/model/data'; + +interface CodeProps { + text: string; + language?: StackVariants; +} + +export const Code: FC = ({ text, language = 'TypeScript' }) => { + const { handleCopy } = useCopy(); + // const [mounted, setMounted] = useState(false); + // const { theme } = useTheme(); + + // useEffect(() => { + // setMounted(true); + // }, []); + + return ( + + + + ); +}; diff --git a/src/shared/ui/code/code.tsx b/src/shared/ui/code/code.tsx deleted file mode 100644 index c5fdb2f..0000000 --- a/src/shared/ui/code/code.tsx +++ /dev/null @@ -1,54 +0,0 @@ -'use client'; - -import { useCopy } from '@/shared/hooks'; -import { ProgrammingLanguage } from '@/shared/types/programming-language'; -import { Theme } from '@/shared/types/theme'; -import { Button, Skeleton, Tooltip } from '@nextui-org/react'; -import { useTheme } from 'next-themes'; -import React, { FC, useEffect, useState } from 'react'; -import SyntaxHighlighter from 'react-syntax-highlighter'; -import { - atomOneDark, - atomOneLight, -} from 'react-syntax-highlighter/dist/esm/styles/hljs'; - -interface CodeProps { - text: string; - language?: ProgrammingLanguage; -} - -export const Code: FC = ({ text, language = 'TypeScript' }) => { - const [mounted, setMounted] = useState(false); - const { theme } = useTheme(); - const { handleCopy } = useCopy(); - - useEffect(() => { - setMounted(true); - }, []); - - if (!mounted) { - return ( - - ); - } - - return ( - - - - ); -}; diff --git a/src/shared/ui/index.ts b/src/shared/ui/index.ts index 8e85d74..b1f10c0 100644 --- a/src/shared/ui/index.ts +++ b/src/shared/ui/index.ts @@ -1,5 +1,5 @@ +import { Code } from './code-block/code'; import { CodeBlock } from './code-block/code-block'; -import { Code } from './code/code'; import { DownloadCvButton } from './download-cv-button/download-cv-button'; import { PageLoader } from './page-loader/page-loader'; import { SidebarNavigation } from './sidebar-navigation/sidebar-navigation'; diff --git a/src/shared/ui/sidebar-navigation/model/data.tsx b/src/shared/ui/sidebar-navigation/model/data.tsx index 00f3900..e996203 100644 --- a/src/shared/ui/sidebar-navigation/model/data.tsx +++ b/src/shared/ui/sidebar-navigation/model/data.tsx @@ -93,29 +93,29 @@ export const SidebarItems: SidebarItemsProps[] = [ { name: 'Next.js: Authentication (Server Components, Actions, Middleware)', link: '/projects/app-router-auth', - gitPath: '/app/projects/app-router-auth/page.tsx', - }, - { - name: 'Hook useMessage', - link: '/projects/use-message', - gitPath: '/src/shared/hooks/useMessage/useMessage.tsx', + gitPath: '/projects/app-router-auth/page.mdx', }, // { + // name: 'Hook useMessage', + // link: '/projects/use-message', + // gitPath: '/src/shared/hooks/useMessage/useMessage.mdx', + // }, + // { // name: 'Infinity scroll + Virtualization', // link: '/projects/infinity-scroll-virtualization', // gitPath: '/app/projects/infinity-scroll-virtualization/page.tsx', // }, ], }, - { - title: 'UI Components', - item: [ - { - name: 'Card 180° Rotating', - link: '/projects/card-rotating', - }, - ], - }, + // { + // title: 'UI Components', + // item: [ + // { + // name: 'Card 180° Rotating', + // link: '/projects/card-rotating', + // }, + // ], + // }, // { // title: '3D Graphics', // item: [ diff --git a/src/shared/ui/stack-buttons/model/data.tsx b/src/shared/ui/stack-buttons/model/data.tsx index cf44e2b..6891e86 100644 --- a/src/shared/ui/stack-buttons/model/data.tsx +++ b/src/shared/ui/stack-buttons/model/data.tsx @@ -1,5 +1,6 @@ import { BiLogoJavascript, BiLogoTypescript } from 'react-icons/bi'; import { MdOutlineCookie } from 'react-icons/md'; +import { PiMarkdownLogo } from 'react-icons/pi'; import { RiNextjsFill } from 'react-icons/ri'; import { SiPrisma } from 'react-icons/si'; import { TbServerBolt } from 'react-icons/tb'; @@ -11,6 +12,7 @@ export type StackVariants = | 'Cookie' | 'Next.js' | 'SSR' + | 'Markdown' | 'Prisma'; interface ButtonProps { @@ -49,4 +51,7 @@ export const StackButtonData: Record = { Prisma: { icon: , }, + Markdown: { + icon: , + }, }; diff --git a/src/shared/ui/text/text.tsx b/src/shared/ui/text/text.tsx index 07bf4c8..e88f85d 100644 --- a/src/shared/ui/text/text.tsx +++ b/src/shared/ui/text/text.tsx @@ -1,20 +1,19 @@ import { cn, toKebabCase, toLatin } from '@/shared/lib'; import Link from 'next/link'; -import { FC } from 'react'; +import { ComponentPropsWithoutRef } from 'react'; +import { FiLink } from 'react-icons/fi'; -interface TextProps { - children: React.ReactNode; - className?: string; - variant?: 'h2' | 'h3'; -} - -export const Text: FC = ({ children, variant, className }) => { - if (variant === 'h2') { - if (typeof children !== 'string') { - throw new Error('Text for "h2" must be a string'); - } - - const id = toKebabCase(toLatin(children)); +export const Text = { + p: ({ children, className }: ComponentPropsWithoutRef<'p'>) => { + return ( +

+ {children} +

+ ); + }, + h2: ({ children }: ComponentPropsWithoutRef<'h2'>) => { + const text = String(children); + const id = toKebabCase(toLatin(text)); return ( <> @@ -29,14 +28,7 @@ export const Text: FC = ({ children, variant, className }) => { > - + {children} @@ -44,11 +36,18 @@ export const Text: FC = ({ children, variant, className }) => { ); - } - - return ( -

- {children} -

- ); + }, + hr: () =>
, + ul: ({ children, className }: ComponentPropsWithoutRef<'ul'>) => { + return ( +
    + {children} +
+ ); + }, }; diff --git a/src/widgets/footer/footer.tsx b/src/widgets/footer/footer.tsx index c550df0..1b4140f 100644 --- a/src/widgets/footer/footer.tsx +++ b/src/widgets/footer/footer.tsx @@ -1,93 +1,16 @@ 'use client'; -import { Button } from '@nextui-org/react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; -import { useEffect, useState } from 'react'; -import { SidebarItems } from '../../shared/ui/sidebar-navigation/model/data'; +import { Footer as MyFooter } from './navigation-button'; export const Footer = () => { + // const {path} = await getProjectData() const pathname = usePathname(); - const [prevPage, setPrevPage] = useState('/'); - const [nextPage, setNextPage] = useState('/'); - const [gitPath, setGitPath] = useState(); - - useEffect(() => { - if (pathname) { - determineNavigationLinks(pathname); - } - }, [pathname]); - - const determineNavigationLinks = (currentPath: string) => { - const allPages = SidebarItems.flatMap((category) => category.item); - const currentIndex = allPages.findIndex( - (page) => page.link === currentPath, - ); - - if (currentIndex > 0) { - setPrevPage(allPages[currentIndex - 1].link); - setGitPath(allPages[currentIndex]?.gitPath); - } else { - setPrevPage('/'); - } - - if (currentIndex < allPages.length - 1) { - setNextPage(allPages[currentIndex + 1].link); - setGitPath(allPages[currentIndex]?.gitPath); - } else { - setNextPage('/'); - } - }; return (
-
- - -
+

Copyright © 2024 Mark Melior.

@@ -97,15 +20,13 @@ export const Footer = () => {

- {gitPath && ( - - Edit this page on GitHub - - )} + + Edit this page on GitHub +
); diff --git a/src/widgets/footer/navigation-button.tsx b/src/widgets/footer/navigation-button.tsx new file mode 100644 index 0000000..cbeddb7 --- /dev/null +++ b/src/widgets/footer/navigation-button.tsx @@ -0,0 +1,90 @@ +'use client'; + +import { Button } from '@nextui-org/react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import React, { useEffect, useState } from 'react'; +import { SidebarItems } from '../../shared/ui/sidebar-navigation/model/data'; + +export const Footer = { + NavigationButton: () => { + const pathname = usePathname(); + const [prevPage, setPrevPage] = useState('/'); + const [nextPage, setNextPage] = useState('/'); + + useEffect(() => { + if (pathname) { + determineNavigationLinks(pathname); + } + }, [pathname]); + + const determineNavigationLinks = (currentPath: string) => { + const allPages = SidebarItems.flatMap((category) => category.item); + const currentIndex = allPages.findIndex( + (page) => page.link === currentPath, + ); + + if (currentIndex > 0) { + setPrevPage(allPages[currentIndex - 1].link); + } else { + setPrevPage('/'); + } + + if (currentIndex < allPages.length - 1) { + setNextPage(allPages[currentIndex + 1].link); + } else { + setNextPage('/'); + } + }; + + return ( +
+ + +
+ ); + }, +}; diff --git a/src/widgets/light/light.tsx b/src/widgets/light/light.tsx index b5f8557..11425b0 100644 --- a/src/widgets/light/light.tsx +++ b/src/widgets/light/light.tsx @@ -28,7 +28,7 @@ export const Light = () => {
- {/* */} +