update
This commit is contained in:
parent
902f734d68
commit
95b6acccd9
|
|
@ -10,7 +10,10 @@ import withReactContent from "sweetalert2-react-content";
|
|||
import { useDropzone } from "react-dropzone";
|
||||
import { close, error, loading } from "@/config/swal";
|
||||
import useDisclosure from "@/components/useDisclosure";
|
||||
import { createAdvertise } from "@/service/advertisement";
|
||||
import {
|
||||
createAdvertise,
|
||||
createMediaFileAdvertise,
|
||||
} from "@/service/advertisement";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
|
|
@ -72,24 +75,32 @@ export default function AdvertisePage() {
|
|||
|
||||
const onSubmit = async (values: z.infer<typeof createArticleSchema>) => {
|
||||
loading();
|
||||
const formData = {
|
||||
title: values.title,
|
||||
description: values.description,
|
||||
placement: placement,
|
||||
redirectLink: values.url,
|
||||
|
||||
const payload = {
|
||||
Title: values.title,
|
||||
Description: values.description,
|
||||
Placement: placement,
|
||||
RedirectLink: values.url,
|
||||
};
|
||||
const res = await createAdvertise(formData);
|
||||
|
||||
const res = await createAdvertise(payload);
|
||||
|
||||
if (res?.error) {
|
||||
error(res?.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// const idNow = res?.data?.data?.id;
|
||||
const idNow = res?.data?.data?.id;
|
||||
|
||||
if (files.length > 0) {
|
||||
if (files.length > 0 && idNow) {
|
||||
const formFiles = new FormData();
|
||||
formFiles.append("file", files[0]);
|
||||
// const resFile = await createMediaFileAdvertise(idNow, formFiles);
|
||||
const resFile = await createMediaFileAdvertise(idNow, formFiles);
|
||||
|
||||
if (resFile?.error) {
|
||||
error(resFile?.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
close();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import Latest from "@/components/landing-page/latest";
|
|||
import LatestandPopular from "@/components/landing-page/latest-and-popular";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import News from "@/components/landing-page/news";
|
||||
import { id } from "date-fns/locale";
|
||||
import Image from "next/image";
|
||||
|
||||
export default function Home() {
|
||||
|
|
@ -27,7 +28,7 @@ export default function Home() {
|
|||
<div className="flex-1">
|
||||
<Header />
|
||||
</div>
|
||||
<Latest />
|
||||
<Latest id={2} />
|
||||
<News />
|
||||
<Author />
|
||||
<LatestandPopular />
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ export default function Login() {
|
|||
Cookies.set("username", profile?.data?.data?.username, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("fullname", profile?.data?.data?.fullname, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("urie", profile?.data?.data?.roleId, {
|
||||
expires: 1,
|
||||
});
|
||||
|
|
@ -192,16 +195,18 @@ export default function Login() {
|
|||
<div className="text-center">
|
||||
<Link href={"/"}>
|
||||
<div className="bg-white/10 backdrop-blur-sm rounded-2xl p-8 shadow-2xl border border-white/20">
|
||||
<img
|
||||
src="/mikul.png"
|
||||
alt="Mikul News Logo"
|
||||
<img
|
||||
src="/mikul.png"
|
||||
alt="Mikul News Logo"
|
||||
className="max-w-xs h-auto drop-shadow-lg"
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="mt-8 text-white/90">
|
||||
<h2 className="text-2xl font-bold mb-2">Portal Mikul News</h2>
|
||||
<p className="text-sm opacity-80">Platform berita terpercaya untuk informasi terkini</p>
|
||||
<p className="text-sm opacity-80">
|
||||
Platform berita terpercaya untuk informasi terkini
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -216,9 +221,9 @@ export default function Login() {
|
|||
{/* Mobile Logo */}
|
||||
<div className="lg:hidden text-center mb-8">
|
||||
<Link href={"/"}>
|
||||
<img
|
||||
src="/mikul.png"
|
||||
alt="Mikul News Logo"
|
||||
<img
|
||||
src="/mikul.png"
|
||||
alt="Mikul News Logo"
|
||||
className="h-12 mx-auto"
|
||||
/>
|
||||
</Link>
|
||||
|
|
@ -228,17 +233,32 @@ export default function Login() {
|
|||
<div className="bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
||||
<div className="text-center mb-8">
|
||||
<div className="w-16 h-16 bg-orange-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-8 h-8 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||
<svg
|
||||
className="w-8 h-8 text-orange-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">Setup Akun</h2>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
Setup Akun
|
||||
</h2>
|
||||
<p className="text-gray-600">Lengkapi informasi email Anda</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<Label htmlFor="old-email" className="text-sm font-medium text-gray-700 mb-2 block">
|
||||
<Label
|
||||
htmlFor="old-email"
|
||||
className="text-sm font-medium text-gray-700 mb-2 block"
|
||||
>
|
||||
Email Lama
|
||||
</Label>
|
||||
<Input
|
||||
|
|
@ -253,7 +273,10 @@ export default function Login() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="new-email" className="text-sm font-medium text-gray-700 mb-2 block">
|
||||
<Label
|
||||
htmlFor="new-email"
|
||||
className="text-sm font-medium text-gray-700 mb-2 block"
|
||||
>
|
||||
Email Baru
|
||||
</Label>
|
||||
<Input
|
||||
|
|
@ -280,29 +303,60 @@ export default function Login() {
|
|||
<div className="bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-8 h-8 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<svg
|
||||
className="w-8 h-8 text-blue-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">Verifikasi OTP</h2>
|
||||
<p className="text-gray-600">Masukkan kode OTP yang telah dikirim</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
Verifikasi OTP
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
Masukkan kode OTP yang telah dikirim
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : isResetPassword ? (
|
||||
<div className="bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
||||
<div className="text-center mb-8">
|
||||
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-8 h-8 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||
<svg
|
||||
className="w-8 h-8 text-red-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">Reset Password</h2>
|
||||
<p className="text-gray-600">Masukkan username untuk reset password</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
Reset Password
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
Masukkan username untuk reset password
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<Label htmlFor="reset-username" className="text-sm font-medium text-gray-700 mb-2 block">
|
||||
<Label
|
||||
htmlFor="reset-username"
|
||||
className="text-sm font-medium text-gray-700 mb-2 block"
|
||||
>
|
||||
Username
|
||||
</Label>
|
||||
<Input
|
||||
|
|
@ -312,9 +366,15 @@ export default function Login() {
|
|||
placeholder="Masukkan username"
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-red-500 focus:border-red-500 transition-colors"
|
||||
value={checkUsernameValue}
|
||||
onChange={(e) => setCheckUsernameValue(e.target.value.trim())}
|
||||
onPaste={(e) => setCheckUsernameValue(e.currentTarget.value.trim())}
|
||||
onCopy={(e) => setCheckUsernameValue(e.currentTarget.value.trim())}
|
||||
onChange={(e) =>
|
||||
setCheckUsernameValue(e.target.value.trim())
|
||||
}
|
||||
onPaste={(e) =>
|
||||
setCheckUsernameValue(e.currentTarget.value.trim())
|
||||
}
|
||||
onCopy={(e) =>
|
||||
setCheckUsernameValue(e.currentTarget.value.trim())
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -348,17 +408,34 @@ export default function Login() {
|
|||
<div className="bg-white rounded-2xl shadow-xl p-8 border border-gray-100">
|
||||
<div className="text-center mb-8">
|
||||
<div className="w-16 h-16 bg-emerald-100 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg className="w-8 h-8 text-emerald-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
|
||||
<svg
|
||||
className="w-8 h-8 text-emerald-600"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">Selamat Datang</h2>
|
||||
<p className="text-gray-600">Portal Mikul News - Platform berita terpercaya</p>
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-2">
|
||||
Selamat Datang
|
||||
</h2>
|
||||
<p className="text-gray-600">
|
||||
Portal Mikul News - Platform berita terpercaya
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<Label htmlFor="username" className="text-sm font-medium text-gray-700 mb-2 block">
|
||||
<Label
|
||||
htmlFor="username"
|
||||
className="text-sm font-medium text-gray-700 mb-2 block"
|
||||
>
|
||||
Username
|
||||
</Label>
|
||||
<Input
|
||||
|
|
@ -369,13 +446,18 @@ export default function Login() {
|
|||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 transition-colors"
|
||||
value={username}
|
||||
onChange={(e) => setValUsername(e.target.value.trim())}
|
||||
onPaste={(e) => setValUsername(e.currentTarget.value.trim())}
|
||||
onPaste={(e) =>
|
||||
setValUsername(e.currentTarget.value.trim())
|
||||
}
|
||||
onCopy={(e) => setValUsername(e.currentTarget.value.trim())}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="password" className="text-sm font-medium text-gray-700 mb-2 block">
|
||||
<Label
|
||||
htmlFor="password"
|
||||
className="text-sm font-medium text-gray-700 mb-2 block"
|
||||
>
|
||||
Password
|
||||
</Label>
|
||||
<div className="relative">
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import Image from "next/image";
|
|||
import { usePathname } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import news from "../news";
|
||||
import Link from "next/link";
|
||||
|
||||
type Article = {
|
||||
id: number;
|
||||
|
|
@ -90,39 +91,44 @@ export default function DevelopmentNews() {
|
|||
{/* Left Content */}
|
||||
<div className="lg:col-span-2 space-y-10">
|
||||
{articles.map((item) => (
|
||||
<div key={item.id} className="flex flex-col md:flex-row gap-6">
|
||||
{/* Image + Category */}
|
||||
<div className="relative w-full md:w-1/2 h-64">
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/placeholder.png"}
|
||||
alt={item.title}
|
||||
fill
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
<span className="absolute top-3 left-3 bg-yellow-400 text-black px-3 py-1 text-xs font-bold">
|
||||
{item.categories[0]?.title || categoryLabel}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1">
|
||||
<h2 className="text-xl font-bold text-[#16324F] hover:text-green-600 cursor-pointer">
|
||||
{item.title}
|
||||
</h2>
|
||||
<div className="text-sm text-gray-600 mt-2">
|
||||
BY{" "}
|
||||
<span className="text-green-600 font-semibold">
|
||||
{item.createdByName || "Admin"}
|
||||
</span>{" "}
|
||||
• {new Date(item.createdAt).toLocaleDateString("id-ID")}
|
||||
<div key={item.id}>
|
||||
<Link
|
||||
className="flex flex-col md:flex-row gap-6"
|
||||
href={`/detail/${item?.id}`}
|
||||
>
|
||||
{/* Image + Category */}
|
||||
<div className="relative w-full md:w-1/2 h-64">
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/placeholder.png"}
|
||||
alt={item.title}
|
||||
fill
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
<span className="absolute top-3 left-3 bg-yellow-400 text-black px-3 py-1 text-xs font-bold">
|
||||
{item.categories[0]?.title || categoryLabel}
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-3 text-gray-700">
|
||||
{truncateText(item.description, 20)}
|
||||
</p>
|
||||
<button className="mt-4 px-4 py-2 border border-gray-400 text-gray-700 hover:bg-black hover:text-white transition">
|
||||
READ MORE
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1">
|
||||
<h2 className="text-xl font-bold text-[#16324F] hover:text-green-600 cursor-pointer">
|
||||
{item.title}
|
||||
</h2>
|
||||
<div className="text-sm text-gray-600 mt-2">
|
||||
BY{" "}
|
||||
<span className="text-green-600 font-semibold">
|
||||
{item.createdByName || "Admin"}
|
||||
</span>{" "}
|
||||
• {new Date(item.createdAt).toLocaleDateString("id-ID")}
|
||||
</div>
|
||||
<p className="mt-3 text-gray-700">
|
||||
{truncateText(item.description, 20)}
|
||||
</p>
|
||||
<button className="mt-4 px-4 py-2 border border-gray-400 text-gray-700 hover:bg-black hover:text-white transition">
|
||||
READ MORE
|
||||
</button>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
|
||||
|
|
@ -198,19 +204,24 @@ export default function DevelopmentNews() {
|
|||
<div className="mt-4 space-y-4">
|
||||
{articles.map((item) => (
|
||||
<div key={item.id} className="flex gap-3 items-center">
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/no-image.jpg"}
|
||||
alt={item.title}
|
||||
width={80}
|
||||
height={60}
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
<div>
|
||||
<h3 className="font-semibold text-sm">{item.title}</h3>
|
||||
<p className="text-xs text-gray-500">
|
||||
{new Date(item.createdAt).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
className="flex gap-3 items-center"
|
||||
href={`/detail/${item?.id}`}
|
||||
>
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/no-image.jpg"}
|
||||
alt={item.title}
|
||||
width={80}
|
||||
height={60}
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
<div>
|
||||
<h3 className="font-semibold text-sm">{item.title}</h3>
|
||||
<p className="text-xs text-gray-500">
|
||||
{new Date(item.createdAt).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -220,93 +231,100 @@ export default function DevelopmentNews() {
|
|||
</h2>
|
||||
<div className=" w-full">
|
||||
<div className="relative w-full aspect-video mb-5">
|
||||
<Image
|
||||
src={
|
||||
articles[0]?.thumbnailUrl ||
|
||||
articles[0]?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/30" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link href={`/detail/${articles[0]?.id}`}>
|
||||
<Image
|
||||
src={
|
||||
articles[0]?.thumbnailUrl ||
|
||||
articles[0]?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/30" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="space-y-5">
|
||||
{articles?.slice(1, 4).map((article, index) => (
|
||||
<div key={index} className="flex gap-3">
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={
|
||||
article?.thumbnailUrl ||
|
||||
article?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article?.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
<div key={index}>
|
||||
<Link
|
||||
className="flex gap-3"
|
||||
href={`/detail/${article?.id}`}
|
||||
>
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={
|
||||
article?.thumbnailUrl ||
|
||||
article?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article?.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// components/Footer.tsx
|
||||
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Footer() {
|
||||
|
|
@ -8,34 +9,48 @@ export default function Footer() {
|
|||
<div className="max-w-7xl mx-auto py-10 bg-[#09282C] px-8">
|
||||
{/* Top Menu Links */}
|
||||
<div className="flex flex-col md:flex-row justify-center md:justify-between gap-3">
|
||||
<div className="w-full md:w-2/12">
|
||||
{/* <div className="w-full md:w-2/12">
|
||||
<p className="text-sm text-gray-400 mt-5">
|
||||
© 2025{" "}
|
||||
<span className="text-xs text-white font-semibold">JNews</span>-
|
||||
Premium WordPress news & magazine theme by{" "}
|
||||
<span className="text-white font-semibold">Jegtheme</span>
|
||||
</p>
|
||||
</div> */}
|
||||
<div className="flex items-center overflow-hidden mb-4 py-6 px-8">
|
||||
<Image
|
||||
src="/mikul.png"
|
||||
alt="Background"
|
||||
width={272}
|
||||
height={90}
|
||||
className="w-full md:w-[272px] h-[90px] object-cover border"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full md:w-6/12">
|
||||
<h2 className="border-b-2 mb-5"></h2>
|
||||
<div className="flex items-start flex-wrap justify-start md:justify-start gap-2 md:gap-3 text-xs text-white font-semibold">
|
||||
{["Beranda ", "Pembangunan", "Kesehatan", "Berita Warga"].map(
|
||||
(item, idx, arr) => (
|
||||
<span
|
||||
key={idx}
|
||||
className="flex items-center gap-2 whitespace-nowrap"
|
||||
>
|
||||
<a href="#" className="hover:underline">
|
||||
{item}
|
||||
</a>
|
||||
{idx !== arr.length - 1 && (
|
||||
<span className="text-white">/</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
{[
|
||||
{ label: "Beranda", href: "#" },
|
||||
{ label: "Pembangunan", href: "/category/development" },
|
||||
{ label: "Kesehatan", href: "/category/health" },
|
||||
{ label: "Berita Warga", href: "/category/citizen-news" },
|
||||
].map((item, idx, arr) => (
|
||||
<span
|
||||
key={idx}
|
||||
className="flex items-center gap-2 whitespace-nowrap"
|
||||
>
|
||||
<a href={item.href} className="hover:underline">
|
||||
{item.label}
|
||||
</a>
|
||||
{idx !== arr.length - 1 && (
|
||||
<span className="text-white">/</span>
|
||||
)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className=" w-full md:w-3/12">
|
||||
<div className="flex flex-col justify-center md:justify-end gap-2 md:gap-3 text-xs text-[#FFFFFF]">
|
||||
<p className="text-xs font-bold text-red-600 mb-2 md:mb-0 w-10/12 text-start">
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export default function HeroNewsSection() {
|
|||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/40 to-transparent p-4 flex flex-col justify-end">
|
||||
<span className="text-xs bg-yellow-400 text-black px-2 py-0.5 inline-block uppercase w-[130px]">
|
||||
{article.categoryName || "TANPA KATEGORI"}
|
||||
{article?.categories?.[0]?.title || "TANPA KATEGORI"}
|
||||
</span>
|
||||
<h3 className="text-sm font-semibold text-white leading-snug mb-1">
|
||||
{article.title}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
import { getListArticle } from "@/service/article";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const data1 = {
|
||||
|
|
@ -249,80 +250,82 @@ export default function LatestandPopular() {
|
|||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
{currentArticles.map((article, index) => (
|
||||
<div key={index}>
|
||||
<div className="relative w-full aspect-video mb-3">
|
||||
<Image
|
||||
src={
|
||||
article?.thumbnailUrl ||
|
||||
article?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={article?.title || "No title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<span className="absolute bottom-1 left-1 bg-[#FFC600] text-black text-[11px] px-2 py-1 uppercase">
|
||||
{article?.categories?.map((cat) => cat.title).join(", ")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-black">
|
||||
<h3 className="font-semibold text-base mb-1">
|
||||
{article.title}
|
||||
</h3>
|
||||
<p className="text-[#999999] text-sm font-serif">
|
||||
{article.description.length > 100
|
||||
? `${article.description.slice(0, 100)}...`
|
||||
: article.description}
|
||||
</p>
|
||||
<div className="text-xs text-[#999999] mb-2 flex items-center gap-2">
|
||||
by{" "}
|
||||
<span className="text-[#31942E]">
|
||||
{article.createdByName}
|
||||
</span>{" "}
|
||||
|{" "}
|
||||
<div className="text-xs mt-1.5 text-[#A0A0A0] space-x-2 flex items-center">
|
||||
{/* Clock Icon + Date */}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<Link href={`/detail/${article?.id}`}>
|
||||
<div className="relative w-full aspect-video mb-3">
|
||||
<Image
|
||||
src={
|
||||
article?.thumbnailUrl ||
|
||||
article?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={article?.title || "No title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<span className="absolute bottom-1 left-1 bg-[#FFC600] text-black text-[11px] px-2 py-1 uppercase">
|
||||
{article?.categories?.map((cat) => cat.title).join(", ")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-black">
|
||||
<h3 className="font-semibold text-base mb-1">
|
||||
{article.title}
|
||||
</h3>
|
||||
<p className="text-[#999999] text-sm font-serif">
|
||||
{article.description.length > 100
|
||||
? `${article.description.slice(0, 100)}...`
|
||||
: article.description}
|
||||
</p>
|
||||
<div className="text-xs text-[#999999] mb-2 flex items-center gap-2">
|
||||
by{" "}
|
||||
<span className="text-[#31942E]">
|
||||
{article.createdByName}
|
||||
</span>{" "}
|
||||
|{" "}
|
||||
<div className="text-xs mt-1.5 text-[#A0A0A0] space-x-2 flex items-center">
|
||||
{/* Clock Icon + Date */}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(article?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-4 w-4"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(article?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-4 w-4"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
||||
/>
|
||||
</svg>{" "}
|
||||
0
|
||||
</svg>{" "}
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -364,93 +367,100 @@ export default function LatestandPopular() {
|
|||
</h2>
|
||||
<div className=" w-full">
|
||||
<div className="relative w-full aspect-video mb-5">
|
||||
<Image
|
||||
src={
|
||||
articles[0]?.thumbnailUrl ||
|
||||
articles[0]?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/30" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link href={`/detail/${articles[0]?.id}`}>
|
||||
<Image
|
||||
src={
|
||||
articles[0]?.thumbnailUrl ||
|
||||
articles[0]?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/30" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="space-y-5">
|
||||
{articles?.slice(1, 4).map((article, index) => (
|
||||
<div key={index} className="flex gap-3">
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={
|
||||
article?.thumbnailUrl ||
|
||||
article?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article?.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
<Link
|
||||
className="flex gap-3"
|
||||
href={`/detail/${article?.id}`}
|
||||
>
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={
|
||||
article?.thumbnailUrl ||
|
||||
article?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article?.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import { getAdvertiseById } from "@/service/advertisement";
|
||||
import { getListArticle } from "@/service/article";
|
||||
import { id } from "date-fns/locale";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const data1 = {
|
||||
|
|
@ -186,7 +189,7 @@ type Article = {
|
|||
}[];
|
||||
};
|
||||
|
||||
export default function Latest() {
|
||||
export default function Latest({ id }: { id: number }) {
|
||||
const [page, setPage] = useState(1);
|
||||
const [totalPage, setTotalPage] = useState(1);
|
||||
const [articles, setArticles] = useState<Article[]>([]);
|
||||
|
|
@ -199,6 +202,17 @@ export default function Latest() {
|
|||
endDate: null,
|
||||
});
|
||||
|
||||
const [data, setData] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const res = await getAdvertiseById(Number(id));
|
||||
const result = res?.data?.data;
|
||||
setData(result);
|
||||
};
|
||||
fetchData();
|
||||
}, [id]);
|
||||
|
||||
useEffect(() => {
|
||||
initState();
|
||||
}, [page, showData, startDateValue, selectedCategories]);
|
||||
|
|
@ -235,85 +249,92 @@ export default function Latest() {
|
|||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 ">
|
||||
<div className=" w-full">
|
||||
<div className="relative w-full aspect-video mb-5">
|
||||
<Image
|
||||
src={articles[0]?.files?.[0]?.file_url || "/nodata.png"}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link href={`/detail/${articles[0]?.id}`}>
|
||||
<Image
|
||||
src={articles[0]?.files?.[0]?.file_url || "/nodata.png"}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="space-y-5">
|
||||
{articles.slice(1, 5).map((article, index) => (
|
||||
<div key={index} className="flex gap-3">
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={article?.thumbnailUrl || "/nodata.png"}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 articles-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
className="flex gap-3"
|
||||
href={`/detail/${article?.id}`}
|
||||
>
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={article?.thumbnailUrl || "/nodata.png"}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 articles-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -321,93 +342,100 @@ export default function Latest() {
|
|||
|
||||
<div className="w-full">
|
||||
<div className="relative w-full aspect-video mb-5">
|
||||
<Image
|
||||
src={
|
||||
articles[0]?.files?.[0]?.file_url || "/default-image.jpg"
|
||||
}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover "
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link href={`/detail/${articles[0]?.id}`}>
|
||||
<Image
|
||||
src={
|
||||
articles[0]?.files?.[0]?.file_url || "/default-image.jpg"
|
||||
}
|
||||
alt={"articles[0]?.title"}
|
||||
fill
|
||||
sizes="(max-width: 1024px) 100vw, 33vw"
|
||||
className="object-cover "
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<div className="absolute bottom-0.5 left-2 text-white">
|
||||
<h3 className=" font-semibold text-base mb-1">
|
||||
{articles[0]?.title}
|
||||
</h3>
|
||||
<p className=" text-xs mb-2 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="space-y-5">
|
||||
{articles.slice(1, 5).map((article, index) => (
|
||||
<div key={index} className="flex gap-3">
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={article?.thumbnailUrl || "/nodata.png"}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover "
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article?.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 articles-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
className="flex gap-3"
|
||||
href={`/detail/${article?.id}`}
|
||||
>
|
||||
<div className="relative w-[120px] h-[86px] shrink-0">
|
||||
<Image
|
||||
src={article?.thumbnailUrl || "/nodata.png"}
|
||||
alt={"article?.title"}
|
||||
fill
|
||||
className="object-cover "
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold mb-3">
|
||||
{article?.title}
|
||||
</h4>
|
||||
<p className="text-xs text-gray-500 flex gap-2 articles-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative my-5 max-w-full h-[125px] overflow-hidden flex items-center mx-auto border">
|
||||
{/* <div className="relative my-5 max-w-full h-[125px] overflow-hidden flex items-center mx-auto border">
|
||||
<Image
|
||||
src="/image-kolom.png"
|
||||
alt="Berita Utama"
|
||||
|
|
@ -434,7 +462,7 @@ export default function Latest() {
|
|||
</h2>
|
||||
<div className="w-full border bg-[#FAFAFA] h-[64px] flex justify-center items-center">
|
||||
<p className="text-center ">No Content Available</p>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<aside className="w-full lg:w-[345px]">
|
||||
|
|
@ -446,86 +474,94 @@ export default function Latest() {
|
|||
<div className="space-y-8">
|
||||
{popularPosts.slice(1, 5).map((post, index) => (
|
||||
<div key={index} className="space-y-3">
|
||||
<div
|
||||
className={`flex gap-4 ${
|
||||
post.files?.[0]?.file_url
|
||||
? "flex-col md:flex-row"
|
||||
: "flex-col"
|
||||
}`}
|
||||
>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-base sm:text-lg md:text-sm font-bold leading-tight">
|
||||
{post?.title}
|
||||
</h3>
|
||||
<div className="text-xs mt-1.5 text-[#A0A0A0] space-x-2 flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<Link href={`/detail/${post?.id}`}>
|
||||
<div
|
||||
className={`flex gap-4 ${
|
||||
post.files?.[0]?.file_url
|
||||
? "flex-col md:flex-row"
|
||||
: "flex-col"
|
||||
}`}
|
||||
>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-base sm:text-lg md:text-sm font-bold leading-tight">
|
||||
{post?.title}
|
||||
</h3>
|
||||
<div className="text-xs mt-1.5 text-[#A0A0A0] space-x-2 flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<g fill="none">
|
||||
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-4 w-4"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
||||
/>
|
||||
</g>
|
||||
</svg>{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-4 w-4"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
||||
/>
|
||||
</svg>{" "}
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{post.thumbnailUrl && (
|
||||
<div className="w-full md:w-1/3 relative">
|
||||
<div className="w-full aspect-[4/3] sm:w-[260px] sm:h-[157px] md:max-w-[320px] md:h-[220px] lg:max-w-[120px] lg:h-[87px] relative ml-auto">
|
||||
<Image
|
||||
src={post?.thumbnailUrl}
|
||||
alt={"post?.title"}
|
||||
fill
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
</svg>{" "}
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-[13px] text-[#3D4248] line-clamp-2 mb-3">
|
||||
{post.description}
|
||||
</p>
|
||||
{post.thumbnailUrl && (
|
||||
<div className="w-full md:w-1/3 relative">
|
||||
<div className="w-full aspect-[4/3] sm:w-[260px] sm:h-[157px] md:max-w-[320px] md:h-[220px] lg:max-w-[120px] lg:h-[87px] relative ml-auto">
|
||||
<Image
|
||||
src={post?.thumbnailUrl}
|
||||
alt={"post?.title"}
|
||||
fill
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-[13px] text-[#3D4248] line-clamp-2 mb-3">
|
||||
{post.description}
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative w-[1111px] max-w-full h-[300px] overflow-hidden flex items-center mx-auto border my-6 rounded">
|
||||
<Image
|
||||
src="/kolom.png"
|
||||
alt="Berita Utama"
|
||||
fill
|
||||
className="object-contain rounded"
|
||||
/>
|
||||
{data?.contentFileUrl ? (
|
||||
<Image
|
||||
src={data.contentFileUrl}
|
||||
alt={data?.title || "Berita Utama"}
|
||||
fill
|
||||
className="object-cover rounded"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full flex items-center justify-center text-gray-400">
|
||||
Loading...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { getListArticle } from "@/service/article";
|
||||
import { Clock } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type postsData = {
|
||||
|
|
@ -60,52 +61,52 @@ export default function Beranda() {
|
|||
return (
|
||||
<section className="max-w-7xl mx-auto px-10 py-5 bg-white">
|
||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between mb-8 pb-1 gap-2 bg-white border-b-2 pt-2 ">
|
||||
<h2 className="text-sm font-bold">Football</h2>
|
||||
<h2 className="text-sm font-bold">Pembangunan</h2>
|
||||
<div className="flex flex-wrap gap-2 text-xs text-gray-600">
|
||||
<button className="hover:text-green-500">ALL</button>
|
||||
<button className="hover:text-green-500">Premier League</button>
|
||||
<button className="hover:text-green-500">The Presidents Cup</button>
|
||||
<button className="hover:text-green-500">Super Bowl</button>
|
||||
<button className="hover:text-green-500">Pembangunan</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 md:gap-10 pt-4 ">
|
||||
{posts.slice(1, 5).map((posts, index) => (
|
||||
<div key={index} className="bg-white overflow-hidden">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={
|
||||
posts.thumbnailUrl ||
|
||||
posts?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={posts.title}
|
||||
width={500}
|
||||
height={300}
|
||||
className="w-full h-52 md:h-56 object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<span className="absolute top-1 left-1 bg-[#FFC600] text-black text-[11px] px-2 py-1 uppercase">
|
||||
{posts.categories?.[0]?.title}
|
||||
</span>
|
||||
<div className="p-3 md:p-2 absolute bottom-1 left-1 text-white">
|
||||
<h3 className="font-bold text-sm md:text-base leading-snug mb-1">
|
||||
{posts.title}
|
||||
</h3>
|
||||
<Link href={`/detail/${posts?.id}`}>
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={
|
||||
posts.thumbnailUrl ||
|
||||
posts?.files?.[0]?.file_url ||
|
||||
"/default-image.jpg"
|
||||
}
|
||||
alt={posts.title}
|
||||
width={500}
|
||||
height={300}
|
||||
className="w-full h-52 md:h-56 object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/20" />
|
||||
<span className="absolute top-1 left-1 bg-[#FFC600] text-black text-[11px] px-2 py-1 uppercase">
|
||||
{posts.categories?.[0]?.title}
|
||||
</span>
|
||||
<div className="p-3 md:p-2 absolute bottom-1 left-1 text-white">
|
||||
<h3 className="font-bold text-sm md:text-base leading-snug mb-1">
|
||||
{posts.title}
|
||||
</h3>
|
||||
|
||||
<div className="text-xs flex items-center gap-2">
|
||||
<Clock className="w-3 h-3 " />
|
||||
<span className=" ">
|
||||
{posts.createdByName} -{" "}
|
||||
{new Date(posts.createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})}
|
||||
</span>
|
||||
<div className="text-xs flex items-center gap-2">
|
||||
<Clock className="w-3 h-3 " />
|
||||
<span className=" ">
|
||||
{posts.createdByName} -{" "}
|
||||
{new Date(posts.createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -126,7 +126,10 @@ export const RetractingSidebar = ({
|
|||
className="hidden md:flex fixed top-4 left-20 z-40 p-3 bg-white rounded-xl shadow-lg border border-slate-200/60 hover:shadow-xl transition-all duration-200 hover:bg-slate-50"
|
||||
onClick={() => updateSidebarData(true)}
|
||||
>
|
||||
<Icon icon="heroicons:chevron-right" className="w-5 h-5 text-slate-600" />
|
||||
<Icon
|
||||
icon="heroicons:chevron-right"
|
||||
className="w-5 h-5 text-slate-600"
|
||||
/>
|
||||
</motion.button>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
|
@ -142,7 +145,10 @@ export const RetractingSidebar = ({
|
|||
className="md:hidden fixed top-4 left-4 z-50 p-3 bg-white dark:bg-slate-800 rounded-xl shadow-lg border border-slate-200/60 dark:border-slate-700/60 hover:shadow-xl transition-all duration-200"
|
||||
onClick={() => updateSidebarData(true)}
|
||||
>
|
||||
<Icon icon="heroicons:chevron-right" className="w-6 h-6 text-slate-600" />
|
||||
<Icon
|
||||
icon="heroicons:chevron-right"
|
||||
className="w-6 h-6 text-slate-600"
|
||||
/>
|
||||
</motion.button>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
|
@ -183,6 +189,17 @@ const SidebarContent = ({
|
|||
updateSidebarData: (newData: boolean) => void;
|
||||
}) => {
|
||||
const { theme, toggleTheme } = useTheme();
|
||||
const [username, setUsername] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
// Ambil cookie secara client-side
|
||||
const cookies = document.cookie.split("; ").reduce((acc: any, cur) => {
|
||||
const [key, value] = cur.split("=");
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
setUsername(cookies.username || "Guest");
|
||||
}, []);
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
{/* SCROLLABLE TOP SECTION */}
|
||||
|
|
@ -193,7 +210,10 @@ const SidebarContent = ({
|
|||
<div className="flex items-center justify-between px-4 py-6">
|
||||
<Link href="/" className="flex items-center space-x-3">
|
||||
<div className="relative">
|
||||
<img src="/mikul.png" className="w-10 h-10 rounded-lg shadow-sm" />
|
||||
<img
|
||||
src="/mikul.png"
|
||||
className="w-10 h-10 rounded-lg shadow-sm"
|
||||
/>
|
||||
<div className="absolute -inset-1 bg-gradient-to-r from-blue-500 to-purple-500 rounded-lg opacity-20 blur-sm"></div>
|
||||
</div>
|
||||
{open && (
|
||||
|
|
@ -210,7 +230,7 @@ const SidebarContent = ({
|
|||
</motion.div>
|
||||
)}
|
||||
</Link>
|
||||
|
||||
|
||||
{open && (
|
||||
<motion.button
|
||||
initial={{ opacity: 0, scale: 0.8 }}
|
||||
|
|
@ -219,9 +239,9 @@ const SidebarContent = ({
|
|||
className="p-2 rounded-lg hover:bg-slate-100 transition-colors duration-200 group"
|
||||
onClick={() => updateSidebarData(false)}
|
||||
>
|
||||
<Icon
|
||||
icon="heroicons:chevron-left"
|
||||
className="w-5 h-5 text-slate-500 group-hover:text-slate-700 transition-colors"
|
||||
<Icon
|
||||
icon="heroicons:chevron-left"
|
||||
className="w-5 h-5 text-slate-500 group-hover:text-slate-700 transition-colors"
|
||||
/>
|
||||
</motion.button>
|
||||
)}
|
||||
|
|
@ -230,7 +250,7 @@ const SidebarContent = ({
|
|||
{/* Navigation Sections */}
|
||||
<div className="space-y-3 px-3 pb-6">
|
||||
{sidebarSections.map((section, sectionIndex) => (
|
||||
<motion.div
|
||||
<motion.div
|
||||
key={section.title}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
|
|
@ -238,7 +258,7 @@ const SidebarContent = ({
|
|||
className="space-y-3"
|
||||
>
|
||||
{open && (
|
||||
<motion.h3
|
||||
<motion.h3
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ delay: 0.2 + sectionIndex * 0.1 }}
|
||||
|
|
@ -271,32 +291,34 @@ const SidebarContent = ({
|
|||
{/* <div className="px-3 pb-2">
|
||||
<div className="h-px bg-gradient-to-r from-transparent via-slate-300 to-transparent"></div>
|
||||
</div> */}
|
||||
|
||||
|
||||
{/* Theme Toggle */}
|
||||
<div className="px-3 pt-1">
|
||||
<motion.button
|
||||
onClick={toggleTheme}
|
||||
className={`relative flex h-12 w-full items-center rounded-xl transition-all duration-200 cursor-pointer group ${
|
||||
open ? 'px-3' : 'justify-center'
|
||||
open ? "px-3" : "justify-center"
|
||||
} ${
|
||||
theme === 'dark'
|
||||
? "bg-gradient-to-r from-emerald-500 to-green-500 text-white shadow-lg shadow-emerald-500/25"
|
||||
theme === "dark"
|
||||
? "bg-gradient-to-r from-emerald-500 to-green-500 text-white shadow-lg shadow-emerald-500/25"
|
||||
: "text-slate-600 hover:bg-gradient-to-r hover:from-slate-100 hover:to-slate-200/50 hover:text-slate-800 dark:text-slate-300 dark:hover:bg-slate-700/50"
|
||||
}`}
|
||||
whileHover={{ scale: 1.02 }}
|
||||
whileTap={{ scale: 0.98 }}
|
||||
>
|
||||
<motion.div
|
||||
<motion.div
|
||||
className={`h-full flex items-center justify-center ${
|
||||
open ? "w-12" : "w-full"
|
||||
}`}
|
||||
>
|
||||
<div className={`text-lg transition-all duration-200 ${
|
||||
theme === 'dark'
|
||||
? "text-white"
|
||||
: "text-slate-500 group-hover:text-slate-700 dark:text-slate-400 dark:group-hover:text-slate-200"
|
||||
}`}>
|
||||
{theme === 'dark' ? (
|
||||
<div
|
||||
className={`text-lg transition-all duration-200 ${
|
||||
theme === "dark"
|
||||
? "text-white"
|
||||
: "text-slate-500 group-hover:text-slate-700 dark:text-slate-400 dark:group-hover:text-slate-200"
|
||||
}`}
|
||||
>
|
||||
{theme === "dark" ? (
|
||||
<Icon icon="solar:sun-bold" className="text-lg" />
|
||||
) : (
|
||||
<Icon icon="solar:moon-bold" className="text-lg" />
|
||||
|
|
@ -305,15 +327,17 @@ const SidebarContent = ({
|
|||
</motion.div>
|
||||
|
||||
{open && (
|
||||
<motion.span
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.1, duration: 0.2 }}
|
||||
<motion.span
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.1, duration: 0.2 }}
|
||||
className={`text-sm font-medium transition-colors duration-200 ${
|
||||
theme === 'dark' ? "text-white" : "text-slate-700 dark:text-slate-300"
|
||||
theme === "dark"
|
||||
? "text-white"
|
||||
: "text-slate-700 dark:text-slate-300"
|
||||
}`}
|
||||
>
|
||||
{theme === 'dark' ? 'Light Mode' : 'Dark Mode'}
|
||||
{theme === "dark" ? "Light Mode" : "Dark Mode"}
|
||||
</motion.span>
|
||||
)}
|
||||
</motion.button>
|
||||
|
|
@ -334,13 +358,19 @@ const SidebarContent = ({
|
|||
</div>
|
||||
|
||||
{/* User Profile */}
|
||||
<motion.div
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ delay: 0.4 }}
|
||||
className="px-3 py-3 border-t border-slate-200/60"
|
||||
>
|
||||
<div className={`${open ? 'flex items-center space-x-3' : 'flex items-center justify-center'} p-3 rounded-xl bg-gradient-to-r from-slate-50 to-slate-100/50 hover:from-slate-100 hover:to-slate-200/50 transition-all duration-200 cursor-pointer group`}>
|
||||
<div
|
||||
className={`${
|
||||
open
|
||||
? "flex items-center space-x-3"
|
||||
: "flex items-center justify-center"
|
||||
} p-3 rounded-xl bg-gradient-to-r from-slate-50 to-slate-100/50 hover:from-slate-100 hover:to-slate-200/50 transition-all duration-200 cursor-pointer group`}
|
||||
>
|
||||
<div className="relative">
|
||||
<div className="w-10 h-10 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 flex items-center justify-center text-white font-semibold text-sm shadow-lg">
|
||||
A
|
||||
|
|
@ -348,13 +378,15 @@ const SidebarContent = ({
|
|||
<div className="absolute -bottom-1 -right-1 w-4 h-4 bg-green-500 rounded-full border-2 border-white"></div>
|
||||
</div>
|
||||
{open && (
|
||||
<motion.div
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: -10 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ delay: 0.5 }}
|
||||
className="flex-1 min-w-0"
|
||||
>
|
||||
<p className="text-sm font-medium text-slate-800 truncate">admin-mabes</p>
|
||||
<p className="text-sm font-medium text-slate-800 truncate">
|
||||
{username}
|
||||
</p>
|
||||
<Link href="/auth">
|
||||
<p className="text-xs text-slate-500 hover:text-blue-600 transition-colors duration-200">
|
||||
Sign out
|
||||
|
|
@ -394,6 +426,17 @@ const SidebarContent = ({
|
|||
const Sidebar = () => {
|
||||
const [open, setOpen] = useState(true);
|
||||
const pathname = usePathname();
|
||||
const [username, setUsername] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
// Ambil cookie secara client-side
|
||||
const cookies = document.cookie.split("; ").reduce((acc: any, cur) => {
|
||||
const [key, value] = cur.split("=");
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
}, {});
|
||||
setUsername(cookies.username || "Guest");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<motion.nav
|
||||
|
|
@ -512,7 +555,7 @@ const Sidebar = () => {
|
|||
</g>
|
||||
</svg>
|
||||
<div className="flex flex-col gap-0.5 text-xs">
|
||||
<p>admin-mabes</p>
|
||||
<p>{username}</p>
|
||||
<p className="underline">Logout</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import Cookies from "js-cookie";
|
||||
import { httpDeleteInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpPostInterceptor,
|
||||
httpPutInterceptor,
|
||||
} from "./http-config/http-interceptor-services";
|
||||
import { httpGet } from "./http-config/http-base-services";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
|
|
@ -8,16 +12,19 @@ export async function createAdvertise(data: any) {
|
|||
const pathUrl = `/advertisement`;
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function createMediaFileAdvertise(id: string | number, data: any) {
|
||||
const headers = {
|
||||
"content-type": "multipart/form-data",
|
||||
"Content-Type": "multipart/form-data",
|
||||
};
|
||||
const pathUrl = `/advertisement/upload/${id}`;
|
||||
return await httpPostInterceptor(pathUrl, data, headers);
|
||||
}
|
||||
|
||||
export async function getAdvertise(data: any) {
|
||||
const pathUrl = `/advertisement?page=${data?.page || 1}&limit=${data?.limit || ""}&placement=${data?.placement || ""}&isPublish=${data.isPublish || ""}`;
|
||||
const pathUrl = `/advertisement?page=${data?.page || 1}&limit=${
|
||||
data?.limit || ""
|
||||
}&placement=${data?.placement || ""}&isPublish=${data.isPublish || ""}`;
|
||||
return await httpGet(pathUrl);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
import Cookies from "js-cookie";
|
||||
import { httpGet, httpPost } from "./http-config/http-base-services";
|
||||
import { httpDeleteInterceptor, httpGetInterceptor, httpPostInterceptor, httpPutInterceptor } from "./http-config/http-interceptor-services";
|
||||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGetInterceptor,
|
||||
httpPostInterceptor,
|
||||
httpPutInterceptor,
|
||||
} from "./http-config/http-interceptor-services";
|
||||
import { hex } from "framer-motion";
|
||||
|
||||
const token = Cookies.get("access_token");
|
||||
const id = Cookies.get("uie");
|
||||
|
|
@ -32,12 +38,12 @@ export async function getDetailMasterUsers(id: string) {
|
|||
}
|
||||
|
||||
export async function editMasterUsers(data: any, id: string) {
|
||||
const pathUrl = `/users/${id}`
|
||||
const pathUrl = `/users/${id}`;
|
||||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
export async function deleteMasterUser(id: string) {
|
||||
const pathUrl = `/users/${id}`
|
||||
const pathUrl = `/users/${id}`;
|
||||
return await httpDeleteInterceptor(pathUrl);
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +55,7 @@ export async function postSignIn(data: any) {
|
|||
export async function getProfile(token?: string) {
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
"Authorization": `Bearer ${token}`,
|
||||
Authorization: `Bearer ${token}`,
|
||||
};
|
||||
const pathUrl = `/users/info`;
|
||||
return await httpGet(pathUrl, headers);
|
||||
|
|
@ -60,7 +66,7 @@ export async function updateProfile(data: any) {
|
|||
return await httpPutInterceptor(pathUrl, data);
|
||||
}
|
||||
export async function savePassword(data: any) {
|
||||
const pathUrl = `/users/save-password`
|
||||
const pathUrl = `/users/save-password`;
|
||||
return await httpPostInterceptor(pathUrl, data);
|
||||
}
|
||||
|
||||
|
|
@ -84,8 +90,8 @@ export async function otpRequest(email: string, name: string) {
|
|||
}
|
||||
|
||||
export async function otpValidation(email: string, otpCode: string) {
|
||||
const pathUrl = `/users/otp-validation`
|
||||
return await httpPost(pathUrl, { email, otpCode });
|
||||
const pathUrl = `/users/otp-validation`;
|
||||
return await httpPost(pathUrl, { email, otpCode });
|
||||
}
|
||||
|
||||
export async function postArticleComment(data: any) {
|
||||
|
|
@ -111,11 +117,14 @@ export async function getArticleComment(id: string) {
|
|||
}
|
||||
|
||||
export async function deleteArticleComment(id: number) {
|
||||
const pathUrl = `/article-comments/${id}`
|
||||
const pathUrl = `/article-comments/${id}`;
|
||||
return await httpDeleteInterceptor(pathUrl);
|
||||
}
|
||||
|
||||
export async function getCsrfToken() {
|
||||
const pathUrl = "csrf-token";
|
||||
return httpGet(pathUrl);
|
||||
}
|
||||
const headers = {
|
||||
"content-type": "application/json",
|
||||
};
|
||||
return httpGet(pathUrl, headers);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue