This commit is contained in:
Anang Yusman 2025-11-02 14:54:24 +08:00
parent ad5e32e96f
commit c2c0cd134a
9 changed files with 78 additions and 31 deletions

View File

@ -0,0 +1,19 @@
import DetailContent from "@/components/details/details-content";
import Footer from "@/components/landing-page/footer";
import Navbar from "@/components/landing-page/navbar";
import Image from "next/image";
export default function Slug() {
return (
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
<div className="relative z-10 bg-[#F2F4F3] max-w-7xl mx-auto">
<Navbar />
<div className="flex-1">
<DetailContent />
</div>
<Footer />
</div>
</div>
);
}

View File

@ -2,7 +2,11 @@
import Image from "next/image";
import { useEffect, useState } from "react";
import Link from "next/link";
import { getArticleById, getListArticle } from "@/service/article";
import {
getArticleById,
getArticleBySlug,
getListArticle,
} from "@/service/article";
import { close, error, loading } from "@/config/swal";
import { useParams, usePathname } from "next/navigation";
import { CommentIcon } from "../icons/sidebar-icon";
@ -17,6 +21,7 @@ import {
postArticleComment,
} from "@/service/master-user";
import { useForm } from "react-hook-form";
import { Badge } from "../ui/badge";
type TabKey = "trending" | "comments" | "latest";
@ -26,6 +31,7 @@ type Article = {
description: string;
categoryName: string;
createdAt: string;
slug: string;
createdByName: string;
customCreatorName: string;
thumbnailUrl: string;
@ -56,6 +62,7 @@ type Advertise = {
export default function DetailContent() {
const params = useParams();
const id = params?.id;
const slug = params?.slug;
const pathname = usePathname();
const [page, setPage] = useState(1);
const [totalPage, setTotalPage] = useState(1);
@ -254,13 +261,13 @@ export default function DetailContent() {
async function initStateData() {
loading();
const res = await getArticleById(id);
const res = await getArticleBySlug(slug);
const data = res.data?.data;
setThumbnail(data?.thumbnailUrl);
setDiseId(data?.aiArticleId);
setDetailFiles(data?.files);
setArticleDetail(data); // <-- Add this
setArticleDetail(data);
close();
}
@ -526,9 +533,17 @@ export default function DetailContent() {
</span>
<div className="flex flex-wrap gap-2 mt-1">
{articleDetail?.tags ? (
<span className="bg-gray-100 text-gray-700 text-sm px-2 py-1 rounded">
{articleDetail.tags}
</span>
articleDetail.tags
.split(",") // pisahkan berdasarkan koma
.map((tag: string, index: number) => (
<Badge
key={index}
variant="secondary"
className="text-sm"
>
{tag.trim()}
</Badge>
))
) : (
<span className="text-sm text-gray-500">Tidak ada tag</span>
)}
@ -694,7 +709,7 @@ export default function DetailContent() {
<div>
<Link
className="flex space-x-3 mb-2"
href={`/detail/${article.id}`}
href={`/details/${article.slug}`}
>
<Image
src={article.thumbnailUrl || "/default-thumb.png"}

View File

@ -10,6 +10,7 @@ type Article = {
description: string;
categoryName: string;
createdAt: string;
slug: string;
createdByName: string;
thumbnailUrl: string;
categories: {
@ -65,7 +66,7 @@ export default function Header() {
key={index}
className="border border-gray-200 overflow-hidden shadow-sm bg-white h-[440px]"
>
<Link href={`/detail/${article?.id}`}>
<Link href={`/details/${article?.slug}`}>
<Image
src={article.thumbnailUrl}
alt={article.title}

View File

@ -72,7 +72,7 @@ export default function HeaderEkonomi() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{articles.map((article) => (
<div key={article.id}>
<Link href={`/detail/${article.id}`}>
<Link href={`/details/${article.slug}`}>
<Image
src={article.thumbnailUrl || "/default.jpg"}
alt={article.title}
@ -98,7 +98,7 @@ export default function HeaderEkonomi() {
})}
</p>
<Link
href={`/detail/${article.id}`}
href={`/details/${article.slug}`}
className="mt-2 inline-block text-sm text-yellow-600 font-semibold hover:underline"
>
READ MORE &gt;
@ -129,7 +129,7 @@ export default function HeaderEkonomi() {
<h4 className="text-xl font-bold">Recent Posts</h4>
{recentPosts.map((post, index) => (
<div key={post.id}>
<Link className="flex gap-3" href={`/detail/${post.id}`}>
<Link className="flex gap-3" href={`/details/${post.slug}`}>
<Image
src={post.thumbnailUrl || "/default.jpg"}
alt={post.title}

View File

@ -11,6 +11,7 @@ type Article = {
description: string;
categoryName: string;
createdAt: string;
slug: string;
createdByName: string;
thumbnailUrl: string;
categories: { title: string }[];
@ -71,7 +72,7 @@ export default function HeaderHealth() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{articles.map((article) => (
<div key={article.id}>
<Link href={`/detail/${article.id}`}>
<Link href={`/details/${article.slug}`}>
<Image
src={article.thumbnailUrl || "/default.jpg"}
alt={article.title}
@ -97,7 +98,7 @@ export default function HeaderHealth() {
})}
</p>
<Link
href={`/detail/${article.id}`}
href={`/details/${article.slug}`}
className="mt-2 inline-block text-sm text-yellow-600 font-semibold hover:underline"
>
READ MORE &gt;
@ -128,7 +129,7 @@ export default function HeaderHealth() {
<h4 className="text-xl font-bold">Recent Posts</h4>
{recentPosts.map((post, index) => (
<div key={post.id}>
<Link className="flex gap-3" href={`/detail/${post.id}`}>
<Link className="flex gap-3" href={`/details/${post.slug}`}>
<Image
src={post.thumbnailUrl || "/default.jpg"}
alt={post.title}

View File

@ -9,6 +9,7 @@ type Article = {
id: number;
title: string;
description: string;
slug: string;
categoryName: string;
createdAt: string;
createdByName: string;
@ -71,7 +72,7 @@ export default function HeaderNarrative() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{articles.map((article) => (
<div key={article.id}>
<Link href={`/detail/${article.id}`}>
<Link href={`/details/${article.slug}`}>
<Image
src={article.thumbnailUrl || "/default.jpg"}
alt={article.title}
@ -97,7 +98,7 @@ export default function HeaderNarrative() {
})}
</p>
<Link
href={`/detail/${article.id}`}
href={`/details/${article.slug}`}
className="mt-2 inline-block text-sm text-yellow-600 font-semibold hover:underline"
>
READ MORE &gt;
@ -128,7 +129,7 @@ export default function HeaderNarrative() {
<h4 className="text-xl font-bold">Recent Posts</h4>
{recentPosts.map((post, index) => (
<div key={post.id}>
<Link className="flex gap-3" href={`/detail/${post.id}`}>
<Link className="flex gap-3" href={`/details/${post.slug}`}>
<Image
src={post.thumbnailUrl || "/default.jpg"}
alt={post.title}

View File

@ -13,6 +13,7 @@ type Article = {
description: string;
categoryName: string;
createdAt: string;
slug: string;
createdByName: string;
thumbnailUrl: string;
categories: {
@ -125,7 +126,7 @@ export default function Beranda() {
<li key={i}>
<Link
className="flex gap-3 items-start"
href={`/detail/${news?.id}`}
href={`/details/${news?.slug}`}
>
<Image
src={news?.thumbnailUrl as string}
@ -150,7 +151,7 @@ export default function Beranda() {
<li key={i}>
<Link
className="flex items-start gap-2 text-sm font-medium border-b"
href={`/detail/${news?.id}`}
href={`/details/${news?.slug}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -182,7 +183,7 @@ export default function Beranda() {
</h2>
<div className="space-y-4 ">
<div>
<Link href={`/detail/${articles[0]?.id}`}>
<Link href={`/details/${articles[0]?.slug}`}>
<div className="relative">
<img
src={articles[0]?.thumbnailUrl}
@ -249,7 +250,7 @@ export default function Beranda() {
<div key={i}>
<Link
className="flex items-start gap-3"
href={`/detail/${item?.id}`}
href={`/details/${item?.slug}`}
>
<img
src={item.thumbnailUrl}
@ -310,7 +311,7 @@ export default function Beranda() {
<div key={article.id}>
<Link
className="flex-shrink-0 flex items-start gap-3 w-[188px]"
href={`/detail/${article?.id}`}
href={`/details/${article?.slug}`}
>
<img
src={article.thumbnailUrl || "/placeholder.jpg"}
@ -339,7 +340,7 @@ export default function Beranda() {
{articles.length > 0 ? (
articles.map((article) => (
<div key={article.id}>
<Link href={`/detail/${article?.id}`}>
<Link href={`/details/${article?.slug}`}>
<img
src={article.thumbnailUrl || "/komjen-pol.jpg"}
alt={article.title}
@ -432,7 +433,7 @@ export default function Beranda() {
>
<Link
className="bg-white shadow-md rounded-none overflow-hidden border"
href={`/detail/${news?.id}`}
href={`/details/${news?.slug}`}
>
<div className="relative">
<img
@ -477,7 +478,7 @@ export default function Beranda() {
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
{articles.map((news, i) => (
<div key={i}>
<Link className="flex gap-4" href={`/detail/${news?.id}`}>
<Link className="flex gap-4" href={`/details/${news?.slug}`}>
<img
src={news.thumbnailUrl}
alt={news.title}
@ -527,7 +528,7 @@ export default function Beranda() {
<div key={i}>
<Link
className="flex flex-col sm:flex-row gap-4 mt-4"
href={`/detail/${recentNews?.id}`}
href={`/details/${recentNews?.slug}`}
>
<img
src={recentNews.thumbnailUrl || "/komjen-pol.jpg"}
@ -590,7 +591,7 @@ export default function Beranda() {
<div className="border" key={i}>
<Link
className="rounded-none overflow-hidden bg-white shadow-sm p-0 gap-1"
href={`/detail/${news?.id}`}
href={`/details/${news?.slug}`}
>
<div className="relative">
{news?.thumbnailUrl && (

View File

@ -199,11 +199,11 @@ export default function ArticleTable() {
initState();
};
const copyUrlArticle = async (id: number) => {
const copyUrlArticle = async (slug: any) => {
const url =
`${window.location.protocol}//${window.location.host}` +
"/detail/" +
`${id}`;
"/details/" +
`${slug}`;
try {
await navigator.clipboard.writeText(url);
successToast("Success", "Article Copy to Clipboard");
@ -263,7 +263,9 @@ export default function ArticleTable() {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuItem onClick={() => copyUrlArticle(article.id)}>
<DropdownMenuItem
onClick={() => copyUrlArticle(article.slug)}
>
<CopyIcon className="mr-2 h-4 w-4" />
Copy Url Article
</DropdownMenuItem>

View File

@ -106,6 +106,13 @@ export async function getArticleById(id: any) {
return await httpGet(`/articles/${id}`, headers);
}
export async function getArticleBySlug(slug: any) {
const headers = {
"content-type": "application/json",
};
return await httpGet(`/articles/slug/${slug}`, headers);
}
export async function deleteArticle(id: string) {
const headers = {
"content-type": "application/json",