Compare commits

...

1 Commits

Author SHA1 Message Date
c2a26cac79 feat: ui implementation
All checks were successful
Frontend CI / build (push) Successful in 1m46s
2025-03-11 23:57:46 +08:00
9 changed files with 172 additions and 0 deletions

View File

@ -8,6 +8,15 @@ const nextConfig: NextConfig = {
env: {
APP_VERSION: process.env.npm_package_version,
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "*",
},
],
},
};
export default nextConfig;

View File

@ -0,0 +1,11 @@
import PostOverallTitle from "@/lib/post/framework/ui/PostOverallTitle";
import PostPreviewCardList from "@/lib/post/framework/ui/PostPreviewCardList";
export default function PostOverallPage() {
return (
<div>
<PostOverallTitle />
<PostPreviewCardList />
</div>
);
}

View File

@ -0,0 +1,7 @@
export default class LabelEntity {
constructor(
public readonly id: number,
public readonly name: string,
public readonly color: string,
) {}
}

View File

@ -0,0 +1,16 @@
import LabelEntity from "@/lib/label/domain/labelEntity";
export default function CompactLabel({ labels }: { labels: LabelEntity[] }) {
function generateTitle(labels: LabelEntity[]): string {
return labels.map((e) => e.name).join("\n");
}
return (
<div
className="flex cursor-default flex-row items-center gap-x-1 rounded-full bg-gray-300 px-2 py-0.5"
title={generateTitle(labels)}
>
<span className="text-xs text-gray-800">{`${labels.length}+`}</span>
</div>
);
}

View File

@ -0,0 +1,13 @@
import LabelEntity from "@/lib/label/domain/labelEntity";
export default function Label({ label }: { label: LabelEntity }) {
return (
<div
className="flex cursor-default flex-row items-center gap-x-1 rounded-full px-2 py-0.5"
style={{ backgroundColor: label.color }}
>
<div className="size-2 rounded-full bg-black opacity-25"></div>
<span className="text-xs text-gray-800">{label.name}</span>
</div>
);
}

View File

@ -0,0 +1,13 @@
import LabelEntity from "@/lib/label/domain/labelEntity";
export default class PostEntity {
constructor(
public id: number,
public title: string,
public content: string,
public description: string,
public previewImageUrl: string,
public labels: LabelEntity[],
public publishedTime: Date,
) {}
}

View File

@ -0,0 +1,7 @@
export default function PostOverallTitle() {
return (
<div className="mx-auto max-w-screen-xl">
<h1 className="py-9 text-center text-3xl font-bold text-gray-800 md:py-20 md:text-5xl"></h1>
</div>
);
}

View File

@ -0,0 +1,23 @@
import Image from "next/image";
import CompactLabel from "@/lib/label/framework/ui/CompactLabel";
import Label from "@/lib/label/framework/ui/Label";
import PostEntity from "../../domain/postEntity";
export default function PostPreviewCard({ post }: { post: PostEntity }) {
return (
<div className="flex flex-col items-start gap-y-4">
<Image alt="Preview Image" src={post.previewImageUrl} width={480} height={270} className="rounded-2xl" />
<div className="flex flex-col items-start gap-y-1.5">
<div className="flex flex-row gap-x-2">
{post.labels.length > 0 && <Label label={post.labels[0]} />}
{post.labels.length > 1 && <CompactLabel labels={post.labels.slice(1)} />}
</div>
<h2 className="text-base font-bold text-gray-800 md:text-lg">{post.title}</h2>
<p className="line-clamp-3 text-sm text-gray-800">{post.description}</p>
<span className="cursor-pointer text-sm text-gray-400"> </span>
</div>
</div>
);
}

View File

@ -0,0 +1,73 @@
import PostEntity from "../../domain/postEntity";
import PostPreviewCard from "./PostPreviewCard";
export default function PostPreviewCardList() {
return (
<div className="mx-auto grid max-w-screen-xl grid-cols-1 gap-x-5 gap-y-6 px-6 pb-6 md:grid-cols-3 md:pb-10">
{postList.map((post) => (
<PostPreviewCard key={post.id} post={post} />
))}
</div>
);
}
const postList: PostEntity[] = [
{
id: 1,
title: "SquidLIVE | 自己的網站自己寫 | 深夜開發台",
content: "SquidLIVE 是一個自己的網站自己寫的深夜開發台,這裡會分享一些技術文章、開發心得、以及一些生活感想。",
description:
"Git Repository: https://git.squidspirit.com/squid/blog 如果喜歡的話就按個大大的喜歡,順便分享出去;如果不喜歡的話也別吝嗇按個不喜歡,也要告訴我原因喔!如有任何問題歡迎在下方留言或寄 E-mail 至squid@squidspirit.com",
previewImageUrl: "https://www.alleycat.org/wp-content/uploads/2019/03/FELV-cat.jpg",
labels: [
{
id: 1,
name: "Software Engineering",
color: "#D9D9D9",
},
{
id: 2,
name: "Algorithm",
color: "#D9D9D9",
},
{
id: 3,
name: "Frontend",
color: "#D9D9D9",
},
],
publishedTime: new Date(),
},
{
id: 2,
title: "SquidLIVE | 自己的網站自己寫 | 深夜開發台",
content: "SquidLIVE 是一個自己的網站自己寫的深夜開發台,這裡會分享一些技術文章、開發心得、以及一些生活感想。",
description:
"Git Repository: https://git.squidspirit.com/squid/blog 如果喜歡的話就按個大大的喜歡,順便分享出去;如果不喜歡的話也別吝嗇按個不喜歡,也要告訴我原因喔!如有任何問題歡迎在下方留言或寄 E-mail 至squid@squidspirit.com",
previewImageUrl: "https://www.alleycat.org/wp-content/uploads/2019/03/FELV-cat.jpg",
labels: [
{
id: 1,
name: "Software Engineering",
color: "#D9D9D9",
},
],
publishedTime: new Date(),
},
{
id: 3,
title: "SquidLIVE | 自己的網站自己寫 | 深夜開發台",
content: "SquidLIVE 是一個自己的網站自己寫的深夜開發台,這裡會分享一些技術文章、開發心得、以及一些生活感想。",
description:
"Git Repository: https://git.squidspirit.com/squid/blog 如果喜歡的話就按個大大的喜歡,順便分享出去;如果不喜歡的話也別吝嗇按個不喜歡,也要告訴我原因喔!如有任何問題歡迎在下方留言或寄 E-mail 至squid@squidspirit.com",
previewImageUrl: "https://www.alleycat.org/wp-content/uploads/2019/03/FELV-cat.jpg",
labels: [
{
id: 1,
name: "Software Engineering",
color: "#D9D9D9",
},
],
publishedTime: new Date(),
},
];