ref(global) update project structure

This commit is contained in:
lumither committed 2024-06-18 13:07:40 +08:00
1 parent 2fabd8d5c0
commit 6b75c17b05
32 files changed
+67 -42

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
import React from 'react';
import ConstructionPlaceHolder from '@/components/ConstructionPlaceHolder';
function About() {
return (
<div className={ `h-dvh` }>
<ConstructionPlaceHolder />
</div>
);
}
export default About;
+12
View File
@@ -0,0 +1,12 @@
import React from 'react';
import ConstructionPlaceHolder from '@/components/ConstructionPlaceHolder';
const Archive = () => {
return (
<div className={ `h-dvh` }>
<ConstructionPlaceHolder />
</div>
);
};
export default Archive;
+94
View File
@@ -0,0 +1,94 @@
import React from 'react';
import { Card, CardBody, CardFooter } from '@nextui-org/card';
import { Chip } from '@nextui-org/react';
import Image from 'next/image';
import Link from 'next/link';
import { MdCalendarMonth, MdNorthEast } from 'react-icons/md';
type Props = {
post: JSON
}
function BlogPostCard({ post }: Props) {
let title = (post as any)['title'];
let sub_title = (post as any)['sub_title'];
// let summary = (post as any)['summary'];
let category = (post as any)['category'];
let tags = (post as any)['tags'];
// let last_update = new Date((post as any)['last_update']);
let first_update = new Date((post as any)['first_update']);
let post_id = (post as any)['post_id'];
let header_img = (post as any)['header_img'];
return (
<div className={ `w-full` }>
<Card as={ Link } href={ `/blog/post/${ post_id }` }
className={ `group` }
isPressable
isHoverable
>
{ header_img !== '' && <div className={ `w-full overflow h-80 relative` }>
<Image
alt={ 'cover picture' }
src={ header_img }
className={ `w-full object-cover rounded-b-none` }
style={ {
'maskImage': 'linear-gradient(black 95%, transparent)',
'backdropFilter': 'blur(20px)'
} }
fill
></Image>
</div> }
<CardBody className={ `overflow-visible` }>
<div className={ `flex flex-row justify-between` }>
<div className={ `mx-2 ${ header_img !== '' ? '-mt-8' : 'mt-2' }` }>
<Chip className={ `mb-2 z-30` } radius={ `sm` } color={ `secondary` }
variant={ `solid` }>{ category }</Chip>
<p className={ `text-4xl font-bold` }> { title }</p>
<p className={ `text-xl` }> { sub_title }</p>
</div>
<MdNorthEast className={ `mt-1 mr-2` } size={ `40px` } />
</div>
</CardBody>
{/* <CardBody className={ `transition-all duration-300 hidden group-hover:block` }>
<div className={ `mx-2` }>
<p>{ summary }</p>
</div>
</CardBody>*/ }
<CardFooter>
<div className={ `flex flex-row flex-wrap justify-between w-full` }>
<div>
<ul className={ `flex flex-row flex-wrap` }>
{
tags.map((tag: string, key: any) => (
<li key={ key } className={ `mx-1 mb-1` }>
<Chip>{ tag }</Chip>
</li>
))
}
</ul>
</div>
<div className={ `flex flex-row place-content-end mb-1 items-center mx-1` }>
<MdCalendarMonth />
<p className={ `text-zinc-500 dark:text-zinc-400 ml-1` }>
{ first_update.toLocaleString('default', {
month: `long`,
day: `numeric`,
year: `numeric`
}) }
</p>
</div>
</div>
</CardFooter>
</Card>
</div>
);
}
export default BlogPostCard;
+9
View File
@@ -0,0 +1,9 @@
import axios from 'axios';
export default async function fetch_posts_list(): Promise<any> {
const response = await axios(`${ process.env.BACKEND_URL }/get_post_list`);
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.data;
}
+15
View File
@@ -0,0 +1,15 @@
import React from 'react';
function Layout({
children
}: {
children: React.ReactNode;
}) {
return (
<div className={ 'flex flex-auto p-7 pl-2 md:pl-7 items-stretch justify-center' }>
{ children }
</div>
);
}
export default Layout;
+39
View File
@@ -0,0 +1,39 @@
import React from 'react';
import fetch_posts_list from '@/app/blog/fetch_posts_list';
import BlogPostCard from '@/app/blog/BlogPostCard';
import { Card, CardBody } from '@nextui-org/card';
import { MotionDiv } from '@/app/public/MotionDiv';
async function Blog() {
try {
const res = await fetch_posts_list();
let posts = res['posts'];
return (
// blog list
<ul className={ 'flex flex-col items-center w-full space-y-7' }>
{ posts.map((post: JSON, key: number) => (
<li key={ key } className={ 'w-full' }>
<MotionDiv
initial={ { y: 20, opacity: 0 } }
animate={ { y: 0, opacity: 1 } }
transition={ { ease: 'easeInOut', duration: 0.5, delay: key * .2 + .25 } }
>
<BlogPostCard post={ post } />
</MotionDiv>
</li>)
) }
</ul>
);
} catch (e: any) {
return (
<Card className={ `w-full` }>
<CardBody>
Fatal: Failed to load post list.
</CardBody>
</Card>);
}
}
export default Blog;
+49
View File
@@ -0,0 +1,49 @@
import React from 'react';
import Markdown from 'react-markdown';
import { Card, CardBody } from '@nextui-org/card';
import remarkGfm from 'remark-gfm';
import rehypeHighlight from 'rehype-highlight';
import rehypeSanitize from 'rehype-sanitize';
import rehypeRaw from 'rehype-raw';
import remarkToc from 'remark-toc';
import remarkFrontmatter from 'remark-frontmatter';
import axios from 'axios';
type Props = {
id: string
}
async function Generate(props: Props) {
let response: any;
try {
response = await axios(`${ process.env.BACKEND_URL }/get_post/${ props.id }`);
} catch (e) {
return (
<Card className={ `w-full` }>
<CardBody>
Fatal: Failed to load the post.
</CardBody>
</Card>
);
}
let post_data = response.data;
return (
<div>
<Card className={ `w-full max-w-full relative` }>
<CardBody>
<Markdown
className={ `p-5 max-w-full text-justify text-pretty prose prose-sm dark:prose-invert md:prose-md lg:prose-lg` }
remarkPlugins={ [ remarkGfm, remarkToc, remarkFrontmatter ] }
rehypePlugins={ [ rehypeHighlight, rehypeRaw, rehypeSanitize ] }
>{ (post_data as any)['content'] }</Markdown>
</CardBody>
</Card>
</div>
);
}
export default Generate;
+20
View File
@@ -0,0 +1,20 @@
import React from 'react';
import Generate from '@/app/blog/post/[id]/generate';
import { MotionDiv } from '@/app/public/MotionDiv';
function BlogReader({ params }: { params: { id: string } }) {
return (
<MotionDiv
initial={ { y: 20, opacity: 0 } }
animate={ { y: 0, opacity: 1 } }
transition={ { ease: 'easeInOut', duration: 0.5 } }
>
<div className={ `w-full` }>
<Generate id={ params.id } />
</div>
</MotionDiv>
);
}
export default BlogReader;
+13
View File
@@ -0,0 +1,13 @@
@import "lxgw-wenkai-webfont/style.css";
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
font-family: "LXGW WenKai", sans-serif;
}
pre, code {
font-family: "LXGW WenKai Mono", sans-serif;
}
+34
View File
@@ -0,0 +1,34 @@
import type { Metadata } from 'next';
import './globals.css';
import React from 'react';
import { ThemeProvider as NextThemesProvider } from 'next-themes';
import Navbar from '@/components/Navbar';
import Footer from '@/components/Footer';
export const metadata: Metadata = {
title: 'Lumither\'s site',
description: 'a small corner on internet'
};
export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body className={ `dark:bg-[#282830] min-h-screen` }>
<NextThemesProvider attribute="class" defaultTheme="dark">
<div className={ `justify-center flex flex-row w-full` }>
<Navbar />
<div className={ `flex flex-col flex-auto max-w-[1024px]` }>
{ children }
<Footer />
</div>
</div>
</NextThemesProvider>
</body>
</html>
);
}
+12
View File
@@ -0,0 +1,12 @@
import ConstructionPlaceHolder from '@/components/ConstructionPlaceHolder';
import React from 'react';
export default function Home() {
return (
<main>
<div className={ `h-dvh` }>
<ConstructionPlaceHolder />
</div>
</main>
);
}
+12
View File
@@ -0,0 +1,12 @@
'use client';
import { NextUIProvider } from '@nextui-org/react';
import React from 'react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<NextUIProvider>
{ children }
</NextUIProvider>
);
}
+5
View File
@@ -0,0 +1,5 @@
'use client';
import { motion } from 'framer-motion';
export const MotionDiv = motion.div;
+7
View File
@@ -0,0 +1,7 @@
export type Result<T, E> = {
ok: true;
value: T;
} | {
ok: false;
error: E;
};
+13
View File
@@ -0,0 +1,13 @@
import React from 'react';
import ConstructionPlaceHolder from '@/components/ConstructionPlaceHolder';
const Search = () => {
return (
<div className={ `h-dvh` }>
<ConstructionPlaceHolder />
</div>
);
};
export default Search;
+12
View File
@@ -0,0 +1,12 @@
import React from 'react';
import ConstructionPlaceHolder from '@/components/ConstructionPlaceHolder';
const Tags = () => {
return (
<div className={ `h-dvh` }>
<ConstructionPlaceHolder />
</div>
);
};
export default Tags;