diff --git a/backend/src/api/post/utils/build_post_idx.rs b/backend/src/api/post/utils/build_post_idx.rs index 3779367..47b2692 100644 --- a/backend/src/api/post/utils/build_post_idx.rs +++ b/backend/src/api/post/utils/build_post_idx.rs @@ -230,7 +230,7 @@ $$ _insert_columns TEXT := 'post_id'; _insert_values TEXT := quote_literal(_post_id); _update_set TEXT := ''; - _blacklist TEXT[] := ARRAY['id', 'tags']; + _blacklist TEXT[] := ARRAY['tags']; BEGIN SELECT EXISTS(SELECT 1 FROM meta WHERE post_id = _post_id) INTO _exists; diff --git a/frontend/app/blog/layout.tsx b/frontend/app/blog/layout.tsx index 6ec814e..058d39a 100644 --- a/frontend/app/blog/layout.tsx +++ b/frontend/app/blog/layout.tsx @@ -7,7 +7,7 @@ function Layout({ }) { return ( //
-
+
{ children }
); diff --git a/frontend/app/blog/post/[id]/Footer.tsx b/frontend/app/blog/post/[id]/Footer.tsx new file mode 100644 index 0000000..38b42b6 --- /dev/null +++ b/frontend/app/blog/post/[id]/Footer.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import MinifyPostCard from '@/app/blog/post/[id]/MinifyPostCard'; +import Link from 'next/link'; +import { FaCreativeCommons } from 'react-icons/fa6'; + +type Props = { + post: any +} + +const Footer = (props: Props) => { + const { post } = props; + + const header_img = post['header_img']; + const adjacent_posts = post['adj']; + const prev_post = adjacent_posts['prev']; + const next_post = adjacent_posts['next']; + const link = post['meta']['link'] ?? `https://lumither.com/blog/post/${ post['meta']['id'] }`; + const author = post['meta']['author'] ?? 'Tao'; + const author_link = post['meta']['author_link'] ?? '/about'; + const post_date = new Date(post['first_update']); + const update_date = new Date(post['last_update']); + const cc = post['meta']['cc'] ?? 'by-nc-sa'; + + + return ( +
+ +
+
+
+
+

{ post['meta']['title'] }

+ +

{ link }

+ +
+
+
+

Author

+ +

{ author }

+ +
+
+

Posted on

+

{ post_date.toLocaleString('default', { + month: `long`, + day: `numeric`, + year: `numeric` + }) }

+
+
+

Updated on

+

{ update_date.toLocaleString('default', { + month: `long`, + day: `numeric`, + year: `numeric` + }) }

+
+
+

Published under

+ +

{ `CC ${ cc.toUpperCase() } 4.0` }

+ +
+
+ +
+
+
+ +
+
+
+ { + next_post && + + } + { + prev_post && + + } +
+
+
+
+ ); +}; +export default Footer; diff --git a/frontend/app/blog/post/[id]/Headers.tsx b/frontend/app/blog/post/[id]/Headers.tsx index 6bba4bf..48c9b9e 100644 --- a/frontend/app/blog/post/[id]/Headers.tsx +++ b/frontend/app/blog/post/[id]/Headers.tsx @@ -10,15 +10,15 @@ type Props = { const Headers = (props: Props) => { let post = props.post; - let title = (post as any)['title']; - let sub_title = (post as any)['sub_title']; + let title = post['title']; + let sub_title = post['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']; + let category = post['category']; + let tags = post['tags']; + // let last_update = new Date((post as any)['last_update']); + let first_update = new Date(post['first_update']); + // let post_id = (post as any)['post_id']; + let header_img = post['header_img']; return ( <> @@ -39,7 +39,7 @@ const Headers = (props: Props) => {
diff --git a/frontend/app/blog/post/[id]/MinifyPostCard.tsx b/frontend/app/blog/post/[id]/MinifyPostCard.tsx new file mode 100644 index 0000000..bf96ee4 --- /dev/null +++ b/frontend/app/blog/post/[id]/MinifyPostCard.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { Card, CardFooter, CardHeader } from '@nextui-org/card'; +import Image from 'next/image'; +import Link from 'next/link'; + +type Props = { + post: any + desc: string +} + +const MinifyPostCard = (props: Props) => { + const { post, desc } = props; + const img_url = post['header_img'] as string; + return ( +
+ + +

{ desc }

+
+ { img_url && +
+ { + +
+

{ post['title'] }

+

{ post['sub_title'] }

+
+
+
+ } + { !img_url && +
+
+

{ post['title'] }

+
+

{ post['sub_title'] }

+
+
+ } +
+ +
+ ); +}; +export default MinifyPostCard; diff --git a/frontend/app/blog/post/[id]/PostCard.tsx b/frontend/app/blog/post/[id]/PostCard.tsx index 5d646cb..c6dbbd3 100644 --- a/frontend/app/blog/post/[id]/PostCard.tsx +++ b/frontend/app/blog/post/[id]/PostCard.tsx @@ -10,6 +10,7 @@ import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'; import rehypeRaw from 'rehype-raw'; import rehypeSanitize from 'rehype-sanitize'; import Headers from '@/app/blog/post/[id]/Headers'; +import Footer from '@/app/blog/post/[id]/Footer'; type Props = { id: string @@ -37,7 +38,7 @@ async function PostCard(props: Props) {
- {/* card headers*/ } + {/* card headers */ } {/* card body */ } @@ -87,6 +88,12 @@ async function PostCard(props: Props) { } } >{ (post_data as any)['content'] } + + + {/* card footer */ } + +
+
); diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index e7b286c..699c751 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -18,7 +18,7 @@ export default function RootLayout({ }>) { return ( - +
diff --git a/frontend/components/Navbar.tsx b/frontend/components/Navbar.tsx index 4d5d147..9d72d3b 100644 --- a/frontend/components/Navbar.tsx +++ b/frontend/components/Navbar.tsx @@ -89,7 +89,7 @@ function Navbar() { }, [ path ]); - const minMobileWidth: number = 768; + const minMobileWidth: number = 1024; const [ isMobile, setIsMobile ] = useState(false); useEffect(() => { const updateMobileWidth = () => { @@ -111,9 +111,9 @@ function Navbar() { return ( <>
+ className={ `flex flex-col min-w-[50px] lg:min-w-[256px] mr-0 lg:mr-2 ml-2 lg:ml-8 min-h-dvh pt-8 sticky` }>
-
+
-
    +
      { connections.map((conn, key) => (
    • @@ -154,7 +154,7 @@ function Navbar() {
+ className={ `flex justify-center lg:justify-start w-full mt-8 ml-0 lg:-ml-3` }>
    { entries.map((meta, key) => ( @@ -165,11 +165,11 @@ function Navbar() { color={ `default` } fullWidth isIconOnly={ isMobile } - className={ 'flex md:justify-start w-fit md:w-full' } + className={ 'flex lg:justify-start w-fit lg:w-full' } aria-label={ `navbar: ${ meta.display_name }` } href={ meta.href }> { meta.icon } - + )) @@ -177,7 +177,7 @@ function Navbar() {
-
+

{ shownPath }

diff --git a/frontend/components/ThemeSwitcher.tsx b/frontend/components/ThemeSwitcher.tsx index 7e0fa55..eda2c48 100644 --- a/frontend/components/ThemeSwitcher.tsx +++ b/frontend/components/ThemeSwitcher.tsx @@ -33,7 +33,7 @@ function ThemeSwitcher() { } } } > - +
); diff --git a/frontend/package.json b/frontend/package.json index 35c8e4f..3b8a622 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -33,6 +33,7 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "autoprefixer": "^10.4.19", "eslint": "^8", "eslint-config-next": "14.2.2", "postcss": "^8", diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs index 1a69fd2..eb160df 100644 --- a/frontend/postcss.config.mjs +++ b/frontend/postcss.config.mjs @@ -1,8 +1,9 @@ /** @type {import('postcss-load-config').Config} */ const config = { - plugins: { - tailwindcss: {}, - }, + plugins: { + tailwindcss: {}, + autoprefixer: {} + } }; export default config;