fix: add landing page tenant and add api bookmark in landing page
|
|
@ -59,7 +59,7 @@ function TenantSettingsContent() {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const [comprehensiveWorkflowRes, userLevelsRes] = await Promise.all([
|
const [comprehensiveWorkflowRes, userLevelsRes] = await Promise.all([
|
||||||
getApprovalWorkflowComprehensiveDetails(), // Using workflow ID 4 as per API example
|
getApprovalWorkflowComprehensiveDetails(),
|
||||||
getUserLevels(),
|
getUserLevels(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import LayoutProvider from "@/providers/layout.provider";
|
||||||
|
import LayoutContentProvider from "@/providers/content.provider";
|
||||||
|
import DashCodeSidebar from "@/components/partials/sidebar";
|
||||||
|
import DashCodeFooter from "@/components/partials/footer";
|
||||||
|
import ThemeCustomize from "@/components/partials/customizer";
|
||||||
|
import DashCodeHeader from "@/components/partials/header";
|
||||||
|
|
||||||
|
import { redirect } from "@/components/navigation";
|
||||||
|
import Footer from "@/components/landing-page/footer";
|
||||||
|
import Navbar from "@/components/landing-page/navbar";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
|
const layout = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const params = useParams();
|
||||||
|
const poldaName: any = params?.polda_name;
|
||||||
|
return (
|
||||||
|
// children
|
||||||
|
// ) : (
|
||||||
|
<>
|
||||||
|
<Navbar />
|
||||||
|
{children}
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default layout;
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import Category from "@/components/landing-page/category";
|
||||||
|
import Footer from "@/components/landing-page/footer";
|
||||||
|
import Header from "@/components/landing-page/header";
|
||||||
|
import MediaUpdate from "@/components/landing-page/media-update";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const page = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<Header />
|
||||||
|
</div>
|
||||||
|
<MediaUpdate />
|
||||||
|
<Category />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default page;
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
|
export const DynamicLogoTenant = () => {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const tenant = pathname?.split("/")[3];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-2">
|
||||||
|
{pathname?.includes("/tenant") && (
|
||||||
|
<Image
|
||||||
|
priority={true}
|
||||||
|
src={`/logo/${tenant}.png`}
|
||||||
|
alt="Logo"
|
||||||
|
width={1920}
|
||||||
|
height={1080}
|
||||||
|
className="object-contain h-[50px] w-[50px] ml-10"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -4,15 +4,26 @@ import { Instagram, ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
|
|
||||||
|
// const logos = [
|
||||||
|
// { src: "/mabes.png", href: "/in/public/publication/kl" },
|
||||||
|
// { src: "/saw.png", href: "/" },
|
||||||
|
// { src: "/mpr.png", href: "/" },
|
||||||
|
// { src: "/dpr.png", href: "/" },
|
||||||
|
// { src: "/ma.png", href: "/" },
|
||||||
|
// { src: "/badan.png", href: "/" },
|
||||||
|
// { src: "/kpk.png", href: "/" },
|
||||||
|
// { src: "/pln.png", href: "/" },
|
||||||
|
// ];
|
||||||
|
|
||||||
const logos = [
|
const logos = [
|
||||||
{ src: "/mabes.png", href: "/public/publication/kl" },
|
{ src: "/mabes.png", slug: "mabes" },
|
||||||
{ src: "/saw.png", href: "/" },
|
{ src: "/saw.png", slug: "kejaksaan-agung" },
|
||||||
{ src: "/mpr.png", href: "/" },
|
{ src: "/mpr.png", slug: "mpr-ri" },
|
||||||
{ src: "/dpr.png", href: "/" },
|
{ src: "/dpr.png", slug: "dpr-ri" },
|
||||||
{ src: "/ma.png", href: "/" },
|
{ src: "/ma.png", slug: "mahkamah-agung" },
|
||||||
{ src: "/badan.png", href: "/" },
|
{ src: "/badan.png", slug: "kemenkeu" },
|
||||||
{ src: "/kpk.png", href: "/" },
|
{ src: "/kpk.png", slug: "kpk" },
|
||||||
{ src: "/pln.png", href: "/" },
|
{ src: "/pln.png", slug: "pupr" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
|
|
@ -51,7 +62,7 @@ export default function Footer() {
|
||||||
{logos.map((logo, idx) => (
|
{logos.map((logo, idx) => (
|
||||||
<a
|
<a
|
||||||
key={idx}
|
key={idx}
|
||||||
href={logo.href}
|
href={`/in/tenant/${logo.slug}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ThumbsUp, ThumbsDown } from "lucide-react";
|
import { ThumbsUp, ThumbsDown } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import { useRouter } from "next/navigation";
|
||||||
getListContent,
|
import Swal from "sweetalert2";
|
||||||
listData,
|
import withReactContent from "sweetalert2-react-content";
|
||||||
listArticles,
|
import { listData, listArticles } from "@/service/landing/landing";
|
||||||
listStaticBanner,
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
} from "@/service/landing/landing";
|
import { toggleBookmark } from "@/service/content";
|
||||||
import { data } from "framer-motion/client";
|
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const [data, setData] = useState<any[]>([]);
|
const [data, setData] = useState<any[]>([]);
|
||||||
const [selectedTab, setSelectedTab] = useState("image");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
// Use new Articles API
|
// 🔹 Gunakan API artikel baru
|
||||||
const response = await listArticles(
|
const response = await listArticles(
|
||||||
1,
|
1,
|
||||||
5,
|
5,
|
||||||
|
|
@ -27,11 +26,9 @@ export default function Header() {
|
||||||
undefined,
|
undefined,
|
||||||
"createdAt"
|
"createdAt"
|
||||||
);
|
);
|
||||||
console.log("Articles API response:", response);
|
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
console.error("Articles API failed, falling back to old API");
|
// fallback ke API lama
|
||||||
// Fallback to old API
|
|
||||||
const fallbackResponse = await listData(
|
const fallbackResponse = await listData(
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
|
@ -48,11 +45,7 @@ export default function Header() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle new API response structure
|
|
||||||
const articlesData = response?.data?.data || [];
|
const articlesData = response?.data?.data || [];
|
||||||
console.log("Articles data:", articlesData);
|
|
||||||
|
|
||||||
// Transform articles data to match old structure for backward compatibility
|
|
||||||
const transformedData = articlesData.map((article: any) => ({
|
const transformedData = articlesData.map((article: any) => ({
|
||||||
id: article.id,
|
id: article.id,
|
||||||
title: article.title,
|
title: article.title,
|
||||||
|
|
@ -63,6 +56,8 @@ export default function Header() {
|
||||||
createdAt: article.createdAt,
|
createdAt: article.createdAt,
|
||||||
smallThumbnailLink: article.thumbnailUrl,
|
smallThumbnailLink: article.thumbnailUrl,
|
||||||
fileTypeId: article.typeId,
|
fileTypeId: article.typeId,
|
||||||
|
tenantName: article.tenantName,
|
||||||
|
categories: article.categories,
|
||||||
label:
|
label:
|
||||||
article.typeId === 1
|
article.typeId === 1
|
||||||
? "Image"
|
? "Image"
|
||||||
|
|
@ -73,13 +68,11 @@ export default function Header() {
|
||||||
: article.typeId === 4
|
: article.typeId === 4
|
||||||
? "Audio"
|
? "Audio"
|
||||||
: "",
|
: "",
|
||||||
...article,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setData(transformedData);
|
setData(transformedData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Gagal memuat data:", error);
|
console.error("Gagal memuat data:", error);
|
||||||
// Try fallback to old API if new API fails
|
|
||||||
try {
|
try {
|
||||||
const fallbackResponse = await listData(
|
const fallbackResponse = await listData(
|
||||||
"",
|
"",
|
||||||
|
|
@ -95,7 +88,7 @@ export default function Header() {
|
||||||
const content = fallbackResponse?.data?.data?.content || [];
|
const content = fallbackResponse?.data?.data?.content || [];
|
||||||
setData(content);
|
setData(content);
|
||||||
} catch (fallbackError) {
|
} catch (fallbackError) {
|
||||||
console.error("Fallback API also failed:", fallbackError);
|
console.error("Fallback API juga gagal:", fallbackError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -127,7 +120,15 @@ export default function Header() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// 🔹 CARD COMPONENT
|
||||||
|
// ========================
|
||||||
function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const MySwal = withReactContent(Swal);
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
const [isBookmarked, setIsBookmarked] = useState(false);
|
||||||
|
|
||||||
const getLink = () => {
|
const getLink = () => {
|
||||||
switch (item?.fileTypeId) {
|
switch (item?.fileTypeId) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
@ -139,11 +140,66 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
case 4:
|
case 4:
|
||||||
return `/content/audio/detail/${item?.id}`;
|
return `/content/audio/detail/${item?.id}`;
|
||||||
default:
|
default:
|
||||||
return "#"; // fallback kalau type tidak dikenali
|
return "#";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ✅ Fungsi simpan bookmark
|
||||||
|
const handleSave = async () => {
|
||||||
|
const roleId = Number(getCookiesDecrypt("urie"));
|
||||||
|
|
||||||
|
// 🔸 Cek apakah user login (roleId ada & valid)
|
||||||
|
if (!roleId || roleId === 0 || isNaN(roleId)) {
|
||||||
|
MySwal.fire({
|
||||||
|
icon: "warning",
|
||||||
|
title: "Login diperlukan",
|
||||||
|
text: "Silakan login terlebih dahulu untuk menyimpan artikel.",
|
||||||
|
confirmButtonText: "Login Sekarang",
|
||||||
|
confirmButtonColor: "#d33",
|
||||||
|
}).then(() => {
|
||||||
|
router.push("/auth");
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsSaving(true);
|
||||||
|
const res = await toggleBookmark(item.id);
|
||||||
|
console.log("Toggle Bookmark Response:", res);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
MySwal.fire({
|
||||||
|
icon: "error",
|
||||||
|
title: "Gagal",
|
||||||
|
text: "Gagal menyimpan artikel.",
|
||||||
|
confirmButtonColor: "#d33",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setIsBookmarked(true);
|
||||||
|
MySwal.fire({
|
||||||
|
icon: "success",
|
||||||
|
title: "Berhasil",
|
||||||
|
text: "Artikel berhasil disimpan ke bookmark.",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
timer: 1500,
|
||||||
|
showConfirmButton: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Toggle bookmark error:", err);
|
||||||
|
MySwal.fire({
|
||||||
|
icon: "error",
|
||||||
|
title: "Kesalahan",
|
||||||
|
text: "Terjadi kesalahan saat menyimpan artikel.",
|
||||||
|
confirmButtonColor: "#d33",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={getLink()}>
|
<div>
|
||||||
<div
|
<div
|
||||||
className={`rounded-xl overflow-hidden shadow hover:shadow-lg transition-all bg-white ${
|
className={`rounded-xl overflow-hidden shadow hover:shadow-lg transition-all bg-white ${
|
||||||
isBig
|
isBig
|
||||||
|
|
@ -156,24 +212,26 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
isBig ? "aspect-[3/2] lg:h-[525px]" : "aspect-video"
|
isBig ? "aspect-[3/2] lg:h-[525px]" : "aspect-video"
|
||||||
} w-full`}
|
} w-full`}
|
||||||
>
|
>
|
||||||
<Image
|
<Link href={getLink()}>
|
||||||
src={item.smallThumbnailLink || "/contributor.png"}
|
<Image
|
||||||
alt={item.title}
|
src={item.smallThumbnailLink || "/contributor.png"}
|
||||||
fill
|
alt={item.title}
|
||||||
className="object-cover"
|
fill
|
||||||
/>
|
className="object-cover"
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 space-y-2">
|
<div className="p-4 space-y-2">
|
||||||
<div className="flex items-center gap-2 text-xs font-semibold flex-wrap">
|
<div className="flex items-center gap-2 text-xs font-semibold flex-wrap">
|
||||||
<span className="bg-emerald-600 text-white px-2 py-0.5 rounded">
|
<span className="bg-emerald-600 text-white px-2 py-0.5 rounded">
|
||||||
{item.categoryName}
|
{item.tenantName}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-orange-600">
|
<span className="text-orange-600">
|
||||||
{" "}
|
|
||||||
{item.categories?.map((cat: any) => cat.title).join(", ")}
|
{item.categories?.map((cat: any) => cat.title).join(", ")}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-xs text-gray-500">
|
<div className="text-xs text-gray-500">
|
||||||
{new Date(item.createdAt)
|
{new Date(item.createdAt)
|
||||||
.toLocaleString("id-ID", {
|
.toLocaleString("id-ID", {
|
||||||
|
|
@ -188,27 +246,257 @@ function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
.replace(".", ":")}{" "}
|
.replace(".", ":")}{" "}
|
||||||
WIB
|
WIB
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-sm font-semibold leading-snug line-clamp-2">
|
|
||||||
{item.title}
|
<Link href={getLink()}>
|
||||||
</h3>
|
<h3 className="text-sm font-semibold leading-snug line-clamp-2">
|
||||||
|
{item.title}
|
||||||
|
</h3>
|
||||||
|
</Link>
|
||||||
|
|
||||||
<div className="flex justify-between items-center pt-2">
|
<div className="flex justify-between items-center pt-2">
|
||||||
<div className="flex gap-2 text-gray-500">
|
<div className="flex gap-2 text-gray-500">
|
||||||
<ThumbsUp
|
<ThumbsUp
|
||||||
size={18}
|
size={18}
|
||||||
className="cursor-pointer hover:text-blue-600"
|
className="cursor-pointer hover:text-[#F60100]"
|
||||||
/>
|
/>
|
||||||
<ThumbsDown
|
<ThumbsDown
|
||||||
size={18}
|
size={18}
|
||||||
className="cursor-pointer hover:text-red-600"
|
className="cursor-pointer hover:text-red-600"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button className="text-sm bg-blue-600 text-white px-3 py-1 rounded-md hover:bg-blue-700">
|
|
||||||
Save
|
{/* ✅ Tombol Save/Disable */}
|
||||||
|
<button
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={isSaving || isBookmarked}
|
||||||
|
className={`text-sm px-3 py-1 rounded-md transition-all duration-200 cursor-pointer ${
|
||||||
|
isBookmarked
|
||||||
|
? "bg-gray-400 text-white cursor-not-allowed"
|
||||||
|
: "bg-[#F60100] text-white hover:bg-[#c90000]"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isSaving ? "Saving..." : isBookmarked ? "Saved" : "Save"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "use client";
|
||||||
|
// import Image from "next/image";
|
||||||
|
// import Link from "next/link";
|
||||||
|
// import { ThumbsUp, ThumbsDown } from "lucide-react";
|
||||||
|
// import { useEffect, useState } from "react";
|
||||||
|
// import {
|
||||||
|
// listData,
|
||||||
|
// listArticles,
|
||||||
|
// } from "@/service/landing/landing";
|
||||||
|
|
||||||
|
// export default function Header() {
|
||||||
|
// const [data, setData] = useState<any[]>([]);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const fetchData = async () => {
|
||||||
|
// try {
|
||||||
|
// // Use new Articles API
|
||||||
|
// const response = await listArticles(
|
||||||
|
// 1,
|
||||||
|
// 5,
|
||||||
|
// undefined,
|
||||||
|
// undefined,
|
||||||
|
// undefined,
|
||||||
|
// "createdAt"
|
||||||
|
// );
|
||||||
|
// console.log("Articles API response:", response);
|
||||||
|
|
||||||
|
// if (response?.error) {
|
||||||
|
// console.error("Articles API failed, falling back to old API");
|
||||||
|
// // Fallback to old API
|
||||||
|
// const fallbackResponse = await listData(
|
||||||
|
// "",
|
||||||
|
// "",
|
||||||
|
// "",
|
||||||
|
// 5,
|
||||||
|
// 0,
|
||||||
|
// "createdAt",
|
||||||
|
// "",
|
||||||
|
// "",
|
||||||
|
// ""
|
||||||
|
// );
|
||||||
|
// const content = fallbackResponse?.data?.data?.content || [];
|
||||||
|
// setData(content);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Handle new API response structure
|
||||||
|
// const articlesData = response?.data?.data || [];
|
||||||
|
// console.log("Articles data:", articlesData);
|
||||||
|
|
||||||
|
// // Transform articles data to match old structure for backward compatibility
|
||||||
|
// const transformedData = articlesData.map((article: any) => ({
|
||||||
|
// id: article.id,
|
||||||
|
// title: article.title,
|
||||||
|
// categoryName:
|
||||||
|
// article.categoryName ||
|
||||||
|
// (article.categories && article.categories[0]?.title) ||
|
||||||
|
// "",
|
||||||
|
// createdAt: article.createdAt,
|
||||||
|
// smallThumbnailLink: article.thumbnailUrl,
|
||||||
|
// fileTypeId: article.typeId,
|
||||||
|
// label:
|
||||||
|
// article.typeId === 1
|
||||||
|
// ? "Image"
|
||||||
|
// : article.typeId === 2
|
||||||
|
// ? "Video"
|
||||||
|
// : article.typeId === 3
|
||||||
|
// ? "Text"
|
||||||
|
// : article.typeId === 4
|
||||||
|
// ? "Audio"
|
||||||
|
// : "",
|
||||||
|
// ...article,
|
||||||
|
// }));
|
||||||
|
|
||||||
|
// setData(transformedData);
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Gagal memuat data:", error);
|
||||||
|
// // Try fallback to old API if new API fails
|
||||||
|
// try {
|
||||||
|
// const fallbackResponse = await listData(
|
||||||
|
// "",
|
||||||
|
// "",
|
||||||
|
// "",
|
||||||
|
// 5,
|
||||||
|
// 0,
|
||||||
|
// "createdAt",
|
||||||
|
// "",
|
||||||
|
// "",
|
||||||
|
// ""
|
||||||
|
// );
|
||||||
|
// const content = fallbackResponse?.data?.data?.content || [];
|
||||||
|
// setData(content);
|
||||||
|
// } catch (fallbackError) {
|
||||||
|
// console.error("Fallback API also failed:", fallbackError);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// fetchData();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <section className="max-w-[1350px] mx-auto px-4">
|
||||||
|
// <div className="flex flex-col lg:flex-row gap-6 py-6">
|
||||||
|
// {data.length > 0 && <Card item={data[0]} isBig />}
|
||||||
|
|
||||||
|
// <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
||||||
|
// {data.slice(1, 5).map((item) => (
|
||||||
|
// <Card key={item.id} item={item} />
|
||||||
|
// ))}
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <div className="relative w-full h-48 sm:h-64 md:h-80 lg:h-[460px] mt-4 rounded-xl">
|
||||||
|
// <Image
|
||||||
|
// src={"/PPS.png"}
|
||||||
|
// alt={"pps"}
|
||||||
|
// fill
|
||||||
|
// className="object-cover rounded-xl"
|
||||||
|
// />
|
||||||
|
// </div>
|
||||||
|
// </section>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function Card({ item, isBig = false }: { item: any; isBig?: boolean }) {
|
||||||
|
// const getLink = () => {
|
||||||
|
// switch (item?.fileTypeId) {
|
||||||
|
// case 1:
|
||||||
|
// return `/content/image/detail/${item?.id}`;
|
||||||
|
// case 2:
|
||||||
|
// return `/content/video/detail/${item?.id}`;
|
||||||
|
// case 3:
|
||||||
|
// return `/content/text/detail/${item?.id}`;
|
||||||
|
// case 4:
|
||||||
|
// return `/content/audio/detail/${item?.id}`;
|
||||||
|
// default:
|
||||||
|
// return "#"; // fallback kalau type tidak dikenali
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// return (
|
||||||
|
// <div>
|
||||||
|
// <div
|
||||||
|
// className={`rounded-xl overflow-hidden shadow hover:shadow-lg transition-all bg-white ${
|
||||||
|
// isBig
|
||||||
|
// ? "w-full lg:max-w-[670px] lg:min-h-[680px]"
|
||||||
|
// : "w-full h-[350px] md:h-[330px]"
|
||||||
|
// }`}
|
||||||
|
// >
|
||||||
|
// <div
|
||||||
|
// className={`relative ${
|
||||||
|
// isBig ? "aspect-[3/2] lg:h-[525px]" : "aspect-video"
|
||||||
|
// } w-full`}
|
||||||
|
// >
|
||||||
|
// <Link href={getLink()}>
|
||||||
|
// {" "}
|
||||||
|
// <Image
|
||||||
|
// src={item.smallThumbnailLink || "/contributor.png"}
|
||||||
|
// alt={item.title}
|
||||||
|
// fill
|
||||||
|
// className="object-cover"
|
||||||
|
// />
|
||||||
|
// </Link>
|
||||||
|
// </div>
|
||||||
|
|
||||||
|
// <div className="p-4 space-y-2">
|
||||||
|
// <div className="flex items-center gap-2 text-xs font-semibold flex-wrap">
|
||||||
|
// <span className="bg-emerald-600 text-white px-2 py-0.5 rounded">
|
||||||
|
// {item.tenantName}
|
||||||
|
// </span>
|
||||||
|
// <span className="text-orange-600">
|
||||||
|
// {" "}
|
||||||
|
// {item.categories?.map((cat: any) => cat.title).join(", ")}
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// <div className="text-xs text-gray-500">
|
||||||
|
// {new Date(item.createdAt)
|
||||||
|
// .toLocaleString("id-ID", {
|
||||||
|
// day: "2-digit",
|
||||||
|
// month: "short",
|
||||||
|
// year: "numeric",
|
||||||
|
// hour: "2-digit",
|
||||||
|
// minute: "2-digit",
|
||||||
|
// hour12: false,
|
||||||
|
// timeZone: "Asia/Jakarta",
|
||||||
|
// })
|
||||||
|
// .replace(".", ":")}{" "}
|
||||||
|
// WIB
|
||||||
|
// </div>
|
||||||
|
// <Link href={getLink()}>
|
||||||
|
// {" "}
|
||||||
|
// <h3 className="text-sm font-semibold leading-snug line-clamp-2">
|
||||||
|
// {item.title}
|
||||||
|
// </h3>
|
||||||
|
// </Link>
|
||||||
|
|
||||||
|
// <div className="flex justify-between items-center pt-2">
|
||||||
|
// <div className="flex gap-2 text-gray-500">
|
||||||
|
// <ThumbsUp
|
||||||
|
// size={18}
|
||||||
|
// className="cursor-pointer hover:text-[#F60100]"
|
||||||
|
// />
|
||||||
|
// <ThumbsDown
|
||||||
|
// size={18}
|
||||||
|
// className="cursor-pointer hover:text-red-600"
|
||||||
|
// />
|
||||||
|
// </div>
|
||||||
|
// <button className="text-sm bg-[#F60100] text-white px-3 py-1 rounded-md hover:bg-[#F60100]">
|
||||||
|
// Save
|
||||||
|
// </button>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
|
||||||
import { Menu, ChevronDown } from "lucide-react";
|
import { Menu, ChevronDown } from "lucide-react";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { Card } from "../ui/card";
|
import { Card } from "../ui/card";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
|
import { Link } from "@/i18n/routing";
|
||||||
|
import { DynamicLogoTenant } from "./dynamic-logo-tenant";
|
||||||
|
|
||||||
const NAV_ITEMS = [
|
const NAV_ITEMS = [
|
||||||
{ label: "Beranda", href: "/" },
|
{ label: "Beranda", href: "/" },
|
||||||
|
|
@ -21,7 +22,7 @@ const NAV_ITEMS = [
|
||||||
|
|
||||||
const PUBLIKASI_SUBMENU = [
|
const PUBLIKASI_SUBMENU = [
|
||||||
{ label: "K/L", href: "/public/publication/kl" },
|
{ label: "K/L", href: "/public/publication/kl" },
|
||||||
{ label: "BUMN", href: "/public/publication/bumn" },
|
{ label: "BUMN", href: "/in/public/publication/bumn" },
|
||||||
{ label: "Pemerintah Daerah", href: "/public/publication/pemerintah-daerah" },
|
{ label: "Pemerintah Daerah", href: "/public/publication/pemerintah-daerah" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -170,6 +171,7 @@ export default function Navbar() {
|
||||||
className="w-6 h-6 cursor-pointer"
|
className="w-6 h-6 cursor-pointer"
|
||||||
onClick={() => setIsSidebarOpen(true)}
|
onClick={() => setIsSidebarOpen(true)}
|
||||||
/>
|
/>
|
||||||
|
<DynamicLogoTenant />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className="absolute left-1/2 -translate-x-1/2 hidden md:flex space-x-3 lg:space-x-8 text-sm font-medium">
|
<nav className="absolute left-1/2 -translate-x-1/2 hidden md:flex space-x-3 lg:space-x-8 text-sm font-medium">
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default function PublicationKlLayout() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const roleId = getCookiesDecrypt("urie") ?? "";
|
const roleId = getCookiesDecrypt("urie") ?? "";
|
||||||
|
|
||||||
const allowedRoles = ["6", "7"];
|
const allowedRoles = ["6", "7", "2", "3"];
|
||||||
|
|
||||||
if (!allowedRoles.includes(roleId)) {
|
if (!allowedRoles.includes(roleId)) {
|
||||||
router.push("/auth");
|
router.push("/auth");
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 326 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 431 KiB |
|
|
@ -392,4 +392,9 @@ export async function listDataTeksNew(
|
||||||
startDate,
|
startDate,
|
||||||
endDate
|
endDate
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function toggleBookmark(articleId: string | number) {
|
||||||
|
const url = `/bookmarks/toggle/${articleId}`;
|
||||||
|
return httpPostInterceptor(url);
|
||||||
}
|
}
|
||||||