update
This commit is contained in:
parent
3417a5f62a
commit
06ab04b26a
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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";
|
||||
|
|
@ -15,6 +19,7 @@ import {
|
|||
} from "@/service/master-user";
|
||||
import { saveActivity } from "@/service/activity-log";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { Badge } from "../ui/badge";
|
||||
|
||||
type TabKey = "trending" | "comments" | "latest";
|
||||
|
||||
|
|
@ -24,6 +29,7 @@ type Article = {
|
|||
description: string;
|
||||
categoryName: string;
|
||||
createdAt: string;
|
||||
slug: string;
|
||||
createdByName: string;
|
||||
thumbnailUrl: string;
|
||||
categories: {
|
||||
|
|
@ -44,6 +50,7 @@ interface CategoryType {
|
|||
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);
|
||||
|
|
@ -214,8 +221,8 @@ export default function DetailContent() {
|
|||
|
||||
async function initStateData() {
|
||||
loading();
|
||||
const res = await getArticleById(id);
|
||||
const data = res.data?.data;
|
||||
const res = await getArticleBySlug(slug);
|
||||
const data = res?.data?.data;
|
||||
|
||||
setThumbnail(data?.thumbnailUrl);
|
||||
setDiseId(data?.aiArticleId);
|
||||
|
|
@ -486,9 +493,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>
|
||||
)}
|
||||
|
|
@ -638,7 +653,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"}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ type Article = {
|
|||
description: string;
|
||||
categoryName: string;
|
||||
createdAt: string;
|
||||
slug: string;
|
||||
createdByName: string;
|
||||
thumbnailUrl: string;
|
||||
categories: { title: string }[];
|
||||
|
|
@ -111,7 +112,7 @@ export default function HeaderGuard() {
|
|||
<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}
|
||||
|
|
@ -137,7 +138,7 @@ export default function HeaderGuard() {
|
|||
})}
|
||||
</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 >
|
||||
|
|
@ -168,7 +169,7 @@ export default function HeaderGuard() {
|
|||
<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}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ type Article = {
|
|||
description: string;
|
||||
categoryName: string;
|
||||
createdAt: string;
|
||||
slug: string;
|
||||
createdByName: string;
|
||||
thumbnailUrl: string;
|
||||
categories: { title: string }[];
|
||||
|
|
@ -112,7 +113,7 @@ export default function HeaderLatest() {
|
|||
<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}
|
||||
|
|
@ -138,7 +139,7 @@ export default function HeaderLatest() {
|
|||
})}
|
||||
</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 >
|
||||
|
|
@ -169,7 +170,7 @@ export default function HeaderLatest() {
|
|||
<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}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ type Article = {
|
|||
id: number;
|
||||
title: string;
|
||||
description: string;
|
||||
slug: string;
|
||||
categoryName: string;
|
||||
createdAt: string;
|
||||
createdByName: string;
|
||||
|
|
@ -111,7 +112,7 @@ export default function HeaderOpinion() {
|
|||
<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}
|
||||
|
|
@ -137,7 +138,7 @@ export default function HeaderOpinion() {
|
|||
})}
|
||||
</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 >
|
||||
|
|
@ -168,7 +169,7 @@ export default function HeaderOpinion() {
|
|||
<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}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type Article = {
|
|||
title: string;
|
||||
description: string;
|
||||
categoryName: string;
|
||||
slug: string;
|
||||
createdAt: string;
|
||||
createdByName: string;
|
||||
thumbnailUrl: string;
|
||||
|
|
@ -111,7 +112,7 @@ export default function HeaderPeace() {
|
|||
<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}
|
||||
|
|
@ -137,7 +138,7 @@ export default function HeaderPeace() {
|
|||
})}
|
||||
</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 >
|
||||
|
|
@ -168,7 +169,7 @@ export default function HeaderPeace() {
|
|||
<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}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type Article = {
|
|||
title: string;
|
||||
description: string;
|
||||
categoryName: string;
|
||||
slug: string;
|
||||
createdAt: string;
|
||||
createdByName: string;
|
||||
thumbnailUrl: string;
|
||||
|
|
@ -111,7 +112,7 @@ export default function HeaderPopular() {
|
|||
<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}
|
||||
|
|
@ -137,7 +138,7 @@ export default function HeaderPopular() {
|
|||
})}
|
||||
</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 >
|
||||
|
|
@ -168,7 +169,7 @@ export default function HeaderPopular() {
|
|||
<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}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ type Article = {
|
|||
categoryName: string;
|
||||
createdAt: string;
|
||||
createdByName: string;
|
||||
slug: string;
|
||||
customCreatorName: string;
|
||||
thumbnailUrl: string;
|
||||
categories: {
|
||||
|
|
@ -68,7 +69,7 @@ export default function Beranda() {
|
|||
{highlightArticles.map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="relative rounded-xl overflow-hidden group"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -103,7 +104,7 @@ export default function Beranda() {
|
|||
{otherArticles.slice(1, 3).map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="flex gap-4 rounded-sm overflow-hidden transition"
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ type Article = {
|
|||
title: string;
|
||||
description: string;
|
||||
categoryName: string;
|
||||
slug: string;
|
||||
createdAt: string;
|
||||
createdByName: string;
|
||||
customCreatorName: string;
|
||||
|
|
@ -111,7 +112,7 @@ export default function Lifestyle() {
|
|||
{articles.slice(0, visibleCount).map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="group block rounded-lg overflow-hidden"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -322,7 +323,7 @@ export default function Lifestyle() {
|
|||
{articles.slice(0, visibleCount).map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="group block rounded-lg overflow-hidden"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -453,7 +454,7 @@ export default function Lifestyle() {
|
|||
{articles.slice(0, visibleCount).map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="group block rounded-lg overflow-hidden"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -522,7 +523,7 @@ export default function Lifestyle() {
|
|||
{articles.slice(0, visibleCount).map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="flex flex-col md:flex-row gap-5 group"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -590,7 +591,7 @@ export default function Lifestyle() {
|
|||
{articles.map((post, idx) => (
|
||||
<Link
|
||||
key={post.id}
|
||||
href={`/detail/${post.id}`}
|
||||
href={`/details/${post.slug}`}
|
||||
className="flex items-start gap-3 group"
|
||||
>
|
||||
{/* Thumbnail */}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ type Article = {
|
|||
description: string;
|
||||
categoryName: string;
|
||||
createdAt: string;
|
||||
slug: string;
|
||||
createdByName: string;
|
||||
customCreatorName: string;
|
||||
thumbnailUrl: string;
|
||||
|
|
@ -114,7 +115,7 @@ export default function OnTheSpot() {
|
|||
{articles.map((item) => (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/detail/${item.id}`}
|
||||
href={`/details/${item.slug}`}
|
||||
className="flex gap-4 rounded-sm overflow-hidden transition"
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue