This commit is contained in:
Anang Yusman 2025-02-17 22:57:44 +08:00
commit c4ba5e44f0
36 changed files with 1933 additions and 769 deletions

View File

@ -23,7 +23,7 @@ RUN pnpm install --frozen-lockfile
COPY . . COPY . .
# Build aplikasi # Build aplikasi
RUN pnpm run build RUN NODE_OPTIONS="--max-old-space-size=4096" pnpm next build
# Expose port untuk server # Expose port untuk server
EXPOSE 3000 EXPOSE 3000

View File

@ -8,13 +8,20 @@ import { Link, useRouter } from "@/i18n/routing";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { BarWave } from "react-cssfx-loading"; import { BarWave } from "react-cssfx-loading";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { checkWishlistStatus, deleteWishlist, getDetail, saveWishlist } from "@/service/landing/landing"; import { checkWishlistStatus, createPublicSuggestion, deletePublicSuggestion, deleteWishlist, getDetail, getPublicSuggestionList, saveWishlist } from "@/service/landing/landing";
import { getCookiesDecrypt } from "@/lib/utils"; import { getCookiesDecrypt } from "@/lib/utils";
import { close, error, loading } from "@/config/swal"; import { close, error, loading, warning } from "@/config/swal";
import { useTranslations } from "next-intl";
import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
import parse from "html-react-parser";
const DetailAudio = () => { const DetailAudio = () => {
const [selectedSize, setSelectedSize] = useState<string>("L"); const [selectedSize, setSelectedSize] = useState<string>("L");
const [selectedTab, setSelectedTab] = useState("video"); const [selectedTab, setSelectedTab] = useState("video");
const t = useTranslations("LandingPage");
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const params = useParams(); const params = useParams();
@ -29,6 +36,11 @@ const DetailAudio = () => {
const [main, setMain] = useState<any>(); const [main, setMain] = useState<any>();
const [resolutionSelected, setResolutionSelected] = useState("720"); const [resolutionSelected, setResolutionSelected] = useState("720");
const [imageSizeSelected, setImageSizeSelected] = useState("l"); const [imageSizeSelected, setImageSizeSelected] = useState("l");
const [message, setMessage] = useState("");
const userRoleId = getCookiesDecrypt("urie");
const [listSuggestion, setListSuggestion] = useState<any>();
const [visibleInput, setVisibleInput] = useState<string | null>(null);
const MySwal = withReactContent(Swal);
const userId = getCookiesDecrypt("uie"); const userId = getCookiesDecrypt("uie");
@ -215,7 +227,120 @@ const DetailAudio = () => {
{ label: "S", value: "1066 x 599 px" }, { label: "S", value: "1066 x 599 px" },
{ label: "XS", value: "800 x 450 px" }, { label: "XS", value: "800 x 450 px" },
]; ];
async function sendSuggestionParent() {
if (message?.length > 3) {
loading();
const data = {
mediaUploadId: slug?.split("-")?.[0],
message,
parentId: null,
};
const response = await createPublicSuggestion(data);
console.log(response);
setMessage("");
const responseGet = await getPublicSuggestionList(slug?.split("-")?.[0]);
console.log(responseGet?.data?.data);
setListSuggestion(responseGet?.data?.data);
// Hapus nilai semua input secara manual jika perlu
const inputs = document.querySelectorAll("input");
inputs.forEach((input) => {
input.value = "";
});
close();
}
}
const getInputValue = (e: any) => {
const message = e.target.value;
console.log(message);
setMessage(message);
};
const postData = () => {
const checkMessage = checkMaliciousText(message);
if (checkMessage == "") {
if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth");
} else {
sendSuggestionParent();
}
} else {
warning(checkMessage);
}
};
function addDefaultProfile(ev: any) {
ev.target.src = "/assets/avatar-profile.png";
}
const showInput = (e: any) => {
console.log(document.querySelector(`#${e}`)?.classList);
document.querySelector(`#${e}`)?.classList.toggle("none");
setVisibleInput(visibleInput === e ? null : e);
};
async function sendSuggestionChild(parentId: any) {
const inputElement = document.querySelector(`#input-comment-${parentId}`) as HTMLInputElement;
if (inputElement && inputElement.value.length > 3) {
loading();
const data = {
mediaUploadId: slug?.split("-")?.[0],
message: inputElement.value,
parentId,
};
console.log(data);
const response = await createPublicSuggestion(data);
console.log(response);
const responseGet: any = await getPublicSuggestionList(slug?.split("-")?.[0]);
console.log(responseGet.data?.data);
setListSuggestion(responseGet.data?.data);
// Reset input field
inputElement.value = "";
// document.querySelector("#comment-id-" + parentId)?.style.display = "none";
close();
}
}
async function deleteDataSuggestion(dataId: any) {
loading();
const response = await deletePublicSuggestion(dataId);
console.log(response);
const responseGet = await getPublicSuggestionList(slug.split("-")?.[0]);
console.log(responseGet.data?.data);
setListSuggestion(responseGet.data?.data);
close();
}
const deleteData = (dataId: any) => {
MySwal.fire({
title: "Delete Comment",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Delete",
}).then((result: any) => {
if (result.isConfirmed) {
deleteDataSuggestion(dataId);
console.log(dataId);
}
});
};
const postDataChild = (id: any) => {
const checkMessage = checkMaliciousText(message);
if (checkMessage == "") {
if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth");
} else {
sendSuggestionChild(id);
}
} else {
warning(checkMessage);
}
};
return ( return (
<> <>
<div className="min-h-screen px-4 md:px-24 py-4"> <div className="min-h-screen px-4 md:px-24 py-4">
@ -316,10 +441,188 @@ const DetailAudio = () => {
<div className="w-full mb-8"> <div className="w-full mb-8">
{/* Comment */} {/* Comment */}
<div className="flex flex-col my-16 gap-5 p-10 bg-gray-300"> {/* <div className="flex flex-col my-16 gap-5 p-10 bg-gray-300">
<p className="flex items-start text-lg">Berikan Komentar</p> <p className="flex items-start text-lg">Berikan Komentar</p>
<Textarea placeholder="Type your comments here." className="flex items-start justify-center" /> <Textarea placeholder="Type your comments here." className="flex items-start justify-center" />
<button className="flex items-start bg-[#bb3523] rounded-lg w-fit px-4 py-1">Kirim</button> <button className="flex items-start bg-[#bb3523] rounded-lg w-fit px-4 py-1">Kirim</button>
</div> */}
<div className="flex flex-col my-16 p-4 lg:p-10 bg-[#f7f7f7]">
<div className="gap-5 flex flex-col px-4 lg:px-14">
<p className="flex items-start text-lg">{t("comment")}</p>
<Textarea placeholder="Type your comments here." className="flex w-full pb-12" onChange={getInputValue} />
<button onClick={() => postData()} className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1">
{t("send")}
</button>
</div>
<div className="border-b-2 border-slate-300 mt-4 w-auto"></div>
<div>
{listSuggestion?.map((data: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:px-14">
<img src={data?.suggestionFrom?.profilePictureUrl} className="h-12 lg:h-16 w-12 lg:w-16 mr-2" onError={addDefaultProfile} alt="" />
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
{Number(data.suggestionFrom?.roleId) == 2 || Number(data.suggestionFrom?.roleId) == 3 || Number(data.suggestionFrom?.roleId) == 4 ? "HUMAS POLRI" : data.suggestionFrom?.fullname}
{getPublicLocaleTimestamp(new Date(data.createdAt))}
</p>
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">{data?.message}</p>
<div>
<a
style={
Number(data.suggestionFrom?.id) == Number(userId)
? {
display: "none",
}
: {}
}
onClick={() => showInput(`comment-id-${data.id}`)}
className="mr-2"
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("reply")}</small>
</a>
{Number(data.suggestionFrom?.id) == Number(userId) || Number(userRoleId) == 2 ? (
<a onClick={() => deleteData(data.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("delete")}</small>
</a>
) : (
""
)}
</div>
</div>
</div>
{visibleInput === `comment-id-${data.id}` && (
<div id={`comment-id-${data.id}`} className="px-4 pl-[72px] lg:px-14 lg:pl-32 mt-2 ">
<Textarea id={`input-comment-${data.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<div className="flex flex-row gap-3">
<a onClick={() => postDataChild(data.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 mt-2 cursor-pointer">{t("send")}</small>
</a>
<a onClick={() => showInput(`comment-id-${data.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg mt-2 w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("cancel")}</small>
</a>
</div>
</div>
)}
{data.children.length > 0
? data.children?.map((child1: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-16 lg:pl-32">
<img src={child1.suggestionFrom?.profilePictureUrl} onError={addDefaultProfile} alt="" className="h-10 lg:h-16 w-10 lg:w-16 mr-2" />
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
{" "}
<b>{Number(child1.suggestionFrom?.roleId) == 2 || Number(child1.suggestionFrom?.roleId) == 3 || Number(child1.suggestionFrom?.roleId) == 4 ? "HUMAS POLRI" : child1.suggestionFrom?.fullname}</b>{" "}
{getPublicLocaleTimestamp(new Date(child1.createdAt))}
</p>
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">{parse(String(child1?.message))}</p>
<div>
<a
style={
Number(child1.suggestionFrom?.id) == Number(userId)
? {
display: "none",
}
: {}
}
onClick={() => showInput(`comment-id-${child1.id}`)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("reply")}</small>
</a>
<a
style={
Number(child1.suggestionFrom?.id) == Number(userId)
? {}
: {
display: "none",
}
}
onClick={() => deleteData(child1.id)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("delete")}</small>
</a>
</div>
</div>
</div>
{visibleInput === `comment-id-${child1.id}` && (
<div id={`comment-id-${child1.id}`} className="px-4 lg:px-14 pl-28 lg:pl-[200px]">
<Textarea name="" className="mt-2 " id={`input-comment-${child1.id}`} placeholder={t("enterReply")} />
<div className="flex flex-row mt-2 gap-3">
<a onClick={() => postDataChild(child1.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("send")}</small>
</a>
<a onClick={() => showInput(`comment-id-${child1.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("cancel")}</small>
</a>
</div>
</div>
)}
{child1.children.length > 0
? child1.children?.map((child2: any) => (
<div className="">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-28 lg:pl-48">
<img src={child2.suggestionFrom?.profilePictureUrl} className="h-9 lg:h-16 w-9 lg:w-16 mr-2" onError={addDefaultProfile} alt="" />
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
{" "}
<b>{Number(child2.suggestionFrom?.roleId) == 2 || Number(child2.suggestionFrom?.roleId) == 3 || Number(child2.suggestionFrom?.roleId) == 4 ? "HUMAS POLRI" : child2.suggestionFrom?.fullname}</b>{" "}
{getPublicLocaleTimestamp(new Date(child2.createdAt))}
</p>
<p className="text-slate-500 text-sm mb-4">{parse(String(child2?.message))}</p>
<div>
<a
style={
Number(child2.suggestionFrom?.id) == Number(userId)
? {
display: "none",
}
: {}
}
onClick={() => showInput(`comment-id-${child2.id}`)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("reply")}</small>
</a>
<a
style={
Number(child2.suggestionFrom?.id) == Number(userId)
? {}
: {
display: "none",
}
}
onClick={() => deleteData(child2.id)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("delete")}</small>
</a>
</div>
</div>
</div>
{visibleInput === `comment-id-${child2.id}` && (
<div id={`comment-id-${child2.id}`} className="px-4 lg:px-14 pl-40 lg:pl-[265px]">
<Textarea name="" id={`input-comment-${child2.id}`} className="my-2" placeholder="Masukkan balasan anda" />
<div className="flex flex-row gap-3">
<a onClick={() => postDataChild(child2.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("send")}</small>
</a>
<a onClick={() => showInput(`comment-id-${child2.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("cancel")}</small>
</a>
</div>
</div>
)}
</div>
))
: ""}
</div>
))
: ""}
</div>
))}
</div>
</div> </div>
{/* Konten Serupa */} {/* Konten Serupa */}

View File

@ -6,10 +6,20 @@ import { Icon } from "@iconify/react/dist/iconify.js";
import NewContent from "@/components/landing-page/new-content"; import NewContent from "@/components/landing-page/new-content";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { getCookiesDecrypt } from "@/lib/utils"; import { getCookiesDecrypt } from "@/lib/utils";
import { checkWishlistStatus, deleteWishlist, getDetail, saveWishlist } from "@/service/landing/landing"; import { checkWishlistStatus, createPublicSuggestion, deletePublicSuggestion, deleteWishlist, getDetail, getPublicSuggestionList, saveWishlist } from "@/service/landing/landing";
import { close, error, loading } from "@/config/swal"; import { close, error, loading, successCallback, warning } from "@/config/swal";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { Link, useRouter } from "@/i18n/routing"; import { Link, useRouter } from "@/i18n/routing";
import { checkMaliciousText, formatDateToIndonesian, getPublicLocaleTimestamp } from "@/utils/globals";
import { useTranslations } from "next-intl";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { useSearchParams } from "next/navigation";
import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking";
import parse from "html-react-parser";
const DetailDocument = () => { const DetailDocument = () => {
const [selectedSize, setSelectedSize] = useState<string>("L"); const [selectedSize, setSelectedSize] = useState<string>("L");
@ -29,6 +39,20 @@ const DetailDocument = () => {
const [main, setMain] = useState<any>(); const [main, setMain] = useState<any>();
const [resolutionSelected, setResolutionSelected] = useState("720"); const [resolutionSelected, setResolutionSelected] = useState("720");
const [imageSizeSelected, setImageSizeSelected] = useState("l"); const [imageSizeSelected, setImageSizeSelected] = useState("l");
const t = useTranslations("LandingPage");
const [message, setMessage] = useState("");
const userRoleId = getCookiesDecrypt("urie");
const [listSuggestion, setListSuggestion] = useState<any>();
const [visibleInput, setVisibleInput] = useState<string | null>(null);
const MySwal = withReactContent(Swal);
const [width, setWidth] = useState<any>();
let typeString = "document";
const [content, setContent] = useState<any>([]);
const [emailShareInput, setEmailShareInput] = useState<any>();
const [emailShareList, setEmailShareList] = useState<any>();
const [emailMessageInput, setEmailMessageInput] = useState();
const searchParams = useSearchParams();
const id = searchParams?.get("id");
const userId = getCookiesDecrypt("uie"); const userId = getCookiesDecrypt("uie");
@ -215,8 +239,282 @@ const DetailDocument = () => {
xhr.send(); xhr.send();
}; };
async function sendSuggestionParent() {
if (message?.length > 3) {
loading();
const data = {
mediaUploadId: slug?.split("-")?.[0],
message,
parentId: null,
};
const response = await createPublicSuggestion(data);
console.log(response);
setMessage("");
const responseGet = await getPublicSuggestionList(slug?.split("-")?.[0]);
console.log(responseGet?.data?.data);
setListSuggestion(responseGet?.data?.data);
// Hapus nilai semua input secara manual jika perlu
const inputs = document.querySelectorAll("input");
inputs.forEach((input) => {
input.value = "";
});
close();
}
}
const getInputValue = (e: any) => {
const message = e.target.value;
console.log(message);
setMessage(message);
};
const postData = () => {
const checkMessage = checkMaliciousText(message);
if (checkMessage == "") {
if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth");
} else {
sendSuggestionParent();
}
} else {
warning(checkMessage);
}
};
function addDefaultProfile(ev: any) {
ev.target.src = "/assets/avatar-profile.png";
}
const showInput = (e: any) => {
console.log(document.querySelector(`#${e}`)?.classList);
document.querySelector(`#${e}`)?.classList.toggle("none");
setVisibleInput(visibleInput === e ? null : e);
};
async function sendSuggestionChild(parentId: any) {
const inputElement = document.querySelector(`#input-comment-${parentId}`) as HTMLInputElement;
if (inputElement && inputElement.value.length > 3) {
loading();
const data = {
mediaUploadId: slug?.split("-")?.[0],
message: inputElement.value,
parentId,
};
console.log(data);
const response = await createPublicSuggestion(data);
console.log(response);
const responseGet: any = await getPublicSuggestionList(slug?.split("-")?.[0]);
console.log(responseGet.data?.data);
setListSuggestion(responseGet.data?.data);
// Reset input field
inputElement.value = "";
// document.querySelector("#comment-id-" + parentId)?.style.display = "none";
close();
}
}
async function deleteDataSuggestion(dataId: any) {
loading();
const response = await deletePublicSuggestion(dataId);
console.log(response);
const responseGet = await getPublicSuggestionList(slug.split("-")?.[0]);
console.log(responseGet.data?.data);
setListSuggestion(responseGet.data?.data);
close();
}
const deleteData = (dataId: any) => {
MySwal.fire({
title: "Delete Comment",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#3085d6",
confirmButtonColor: "#d33",
confirmButtonText: "Delete",
}).then((result: any) => {
if (result.isConfirmed) {
deleteDataSuggestion(dataId);
console.log(dataId);
}
});
};
const postDataChild = (id: any) => {
const checkMessage = checkMaliciousText(message);
if (checkMessage == "") {
if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth");
} else {
sendSuggestionChild(id);
}
} else {
warning(checkMessage);
}
};
const handleShare = (type: any, url: any) => {
if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth/login");
} else {
sendActivityLog(2);
sendActivityLog(4);
if (type == "wa" && width <= 768) {
window.open(`whatsapp://send?${url}`, "_blank");
} else if (type == "wa" && width > 768) {
window.open(`https://web.whatsapp.com/send?${url}`, "_blank", "noreferrer");
} else {
window.open(url);
}
}
};
const handleEmailList = (e: any) => {
const arrayEmail: any = [];
for (let i = 0; i < emailShareList?.length; i += 1) {
arrayEmail.push(emailShareList[i]);
}
if (e.which == 13) {
if (e.target.value) {
arrayEmail.push(e.target.value);
setEmailShareList(arrayEmail);
setEmailShareInput("");
}
e.preventDefault();
}
return false;
};
async function shareToEmail() {
if (Number(userRoleId) < 1 || userRoleId == undefined) {
router.push("/auth/login");
} else {
const data = {
mediaUploadId: id?.split("-")?.[0],
email: emailShareList || [emailShareInput],
message: emailMessageInput,
url: window.location.href,
};
loading();
const res = await sendMediaUploadToEmail(data);
if (res?.error) {
error(res.message);
return false;
}
close();
successCallback("Konten Telah Dikirim");
}
}
return ( return (
// <>
// <div className="px-4 md:px-24 py-4">
// <div className="rounded-md overflow-hidden md:flex">
// {/* Bagian Kiri */}
// <div className="md:w-3/4">
// <div className="relative">
// <img src={detailDataDocument?.files[selectedDocument]?.url} alt="Main" className="rounded-lg w-auto h-fit" />
// <div className="absolute top-4 left-4"></div>
// </div>
// {/* Footer Informasi */}
// <div className="text-sm text-gray-500 flex justify-between items-center border-t mt-4">
// <p className="flex flex-row items-center mt-3">
// oleh&nbsp;<span className="font-semibold text-black">{detailDataDocument?.uploadedBy?.userLevel?.name}</span>&nbsp;|&nbsp;Diupdate pada {detailDataDocument?.updatedAt} WIB&nbsp;|&nbsp;
// <Icon icon="formkit:eye" width="15" height="15" />
// &nbsp;
// {detailDataDocument?.clickCount}
// </p>
// <p className="mt-3">Kreator: {detailDataDocument?.creatorName}</p>
// </div>
// {/* Keterangan */}
// <div className="md:w-3/4">
// <h1 className="flex flex-row font-bold text-2xl my-8">{detailDataDocument?.title}</h1>
// <div dangerouslySetInnerHTML={{ __html: detailDataDocument?.htmlDescription }} />
// </div>
// </div>
// {/* Bagian Kanan */}
// <div className="md:w-1/4 p-4 bg-[#f7f7f7] h-fit rounded-lg mx-4">
// {isSaved ? (
// <a onClick={() => handleDeleteWishlist()} className="flex flex-col mb-3 items-center justify-center cursor-pointer">
// <Icon icon="material-symbols:bookmark" width={40} />
// <p className="text-base lg:text-lg">Hapus</p>
// </a>
// ) : (
// <a onClick={() => doBookmark()} className="flex flex-col mb-3 items-center justify-center cursor-pointer">
// <Icon icon="material-symbols:bookmark-outline" width={40} />
// <p className="text-base lg:text-lg">Simpan</p>
// </a>
// )}
// {/* garis */}
// <div className="border-t border-black my-4"></div>
// <Link href={`/all/filter?title=polda&category=${detailDataDocument?.category.id}`} className="bg-red-600 text-white text-xs font-bold px-3 py-3 my-3 flex justify-center items-center rounded">
// {detailDataDocument?.category?.name}
// </Link>
// <div className="flex justify-center flex-wrap gap-2 mb-4">
// {detailDataDocument?.tags?.split(",").map((tag: string) => (
// <a onClick={() => router.push(`/all/filter?tag=${tag}`)} key={tag} className="bg-gray-200 text-gray-700 text-xs px-3 py-1 rounded-full cursor-pointer hover:bg-gray-500">
// {tag}
// </a>
// ))}
// </div>
// <div className="border-t border-black my-4"></div>
// {/* Opsi Ukuran Foto */}
// <h4 className="flex text-lg justify-center items-center font-semibold my-3">Opsi Ukuran Foto</h4>
// <div className="border-t border-black my-4"></div>
// <div className="space-y-2">
// {sizes.map((size: any) => (
// <div className="flex flex-row justify-between">
// <div key={size.label} className="items-center flex flex-row gap-2 cursor-pointer">
// <input type="radio" name="size" value={size.label} checked={selectedSize === size.label} onChange={() => setSelectedSize(size.label)} className="text-red-600 focus:ring-red-600" />
// <div className="text-sm">{size.label}</div>
// </div>
// <div className="">
// <div className="text-sm">{size.value}</div>
// </div>
// </div>
// ))}
// </div>
// {/* Download Semua */}
// <div className="mt-4">
// <label className="flex items-center space-x-2 text-sm">
// <input type="checkbox" className="text-red-600 focus:ring-red-600" onChange={() => setIsDownloadAll(!isDownloadAll)} />
// <span>Download Semua File?</span>
// </label>
// </div>
// {/* Tombol Download */}
// <button onClick={handleDownload} className="mt-4 bg-red-600 text-white w-full py-2 flex justify-center items-center gap-1 rounded-md text-sm hover:bg-red-700">
// <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
// <path fill="white" d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z" />
// </svg>
// Download
// </button>
// </div>
// </div>
// </div>
// <div className="w-full mb-8">
// {/* Comment */}
// <div className="flex flex-col my-16 p-10 bg-[#f7f7f7]">
// <div className="gap-5 flex flex-col px-4 lg:px-16">
// <p className="flex items-start text-lg">Berikan Komentar</p>
// <Textarea placeholder="Type your comments here." className="flex w-full" />
// <button className="flex items-start bg-[#bb3523] rounded-lg text-white w-fit px-4 py-1">Kirim</button>
// </div>
// </div>
// {/* Konten Serupa */}
// <div className="">
// <NewContent group="polda" type={"similar"} />
// </div>
// </div>
// </>
<> <>
<div className="px-4 md:px-24 py-4"> <div className="px-4 md:px-24 py-4">
<div className="rounded-md overflow-hidden md:flex"> <div className="rounded-md overflow-hidden md:flex">
@ -227,19 +525,42 @@ const DetailDocument = () => {
<div className="absolute top-4 left-4"></div> <div className="absolute top-4 left-4"></div>
</div> </div>
{/* Footer Informasi */} {/* Footer Informasi */}
<div className="text-sm text-gray-500 flex justify-between items-center border-t mt-4"> <div className="text-gray-500 flex flex-col lg:flex-row justify-between items-center border-t mt-4">
<p className="flex flex-row items-center mt-3"> {/* <p className="flex flex-row items-center mt-3">
oleh&nbsp;<span className="font-semibold text-black">{detailDataDocument?.uploadedBy?.userLevel?.name}</span>&nbsp;|&nbsp;Diupdate pada {detailDataDocument?.updatedAt} WIB&nbsp;|&nbsp; oleh&nbsp;<span className="font-semibold text-black">{detailDataDocument?.uploadedBy?.userLevel?.name}</span>&nbsp;|&nbsp;Diupdate pada {detailDataDocument?.updatedAt} WIB&nbsp;|&nbsp;
<Icon icon="formkit:eye" width="15" height="15" /> <Icon icon="formkit:eye" width="15" height="15" />
&nbsp; &nbsp;
{detailDataDocument?.clickCount} {detailDataDocument?.clickCount}
</p> </p>
<p className="mt-3">Kreator: {detailDataDocument?.creatorName}</p> <p className="mt-3">Kreator: {detailDataDocument?.creatorName}</p> */}
<div className="flex flex-col lg:flex-row items-center mt-3 lg:justify-between">
<p className="text-xs lg:text-sm">
{t("by")}&nbsp;<span className="font-semibold text-black">{detailDataDocument?.uploadedBy?.userLevel?.name}</span>
</p>
{/* <p className="text-xs lg:text-sm">
&nbsp;|&nbsp; {t("updatedOn")} {detailDataDocument?.updatedAt} WIB &nbsp;|&nbsp;
</p> */}
<p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")}&nbsp;
{formatDateToIndonesian(new Date(detailDataDocument?.updatedAt))} {"WIB"}
</p>
<p className="text-xs lg:text-sm flex justify-center items-center">
&nbsp;| &nbsp;
<Icon icon="formkit:eye" width="15" height="15" />
&nbsp;{detailDataDocument?.clickCount}&nbsp;
</p>
</div>
<div className="mt-3">
<p className="flex text-end text-xs lg:text-sm font-semibold">
{t("creator")}
{detailDataDocument?.creatorName}
</p>
</div>
</div> </div>
{/* Keterangan */} {/* Keterangan */}
<div className="md:w-3/4"> <div className="">
<h1 className="flex flex-row font-bold text-2xl my-8">{detailDataDocument?.title}</h1> <h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8 text-justify space-y-4">{detailDataDocument?.title}</h1>
<div dangerouslySetInnerHTML={{ __html: detailDataDocument?.htmlDescription }} /> <div dangerouslySetInnerHTML={{ __html: detailDataDocument?.htmlDescription }} />
</div> </div>
</div> </div>
@ -249,12 +570,12 @@ const DetailDocument = () => {
{isSaved ? ( {isSaved ? (
<a onClick={() => handleDeleteWishlist()} className="flex flex-col mb-3 items-center justify-center cursor-pointer"> <a onClick={() => handleDeleteWishlist()} className="flex flex-col mb-3 items-center justify-center cursor-pointer">
<Icon icon="material-symbols:bookmark" width={40} /> <Icon icon="material-symbols:bookmark" width={40} />
<p className="text-base lg:text-lg">Hapus</p> <p className="text-base lg:text-lg">{t("delete")}</p>
</a> </a>
) : ( ) : (
<a onClick={() => doBookmark()} className="flex flex-col mb-3 items-center justify-center cursor-pointer"> <a onClick={() => doBookmark()} className="flex flex-col mb-3 items-center justify-center cursor-pointer">
<Icon icon="material-symbols:bookmark-outline" width={40} /> <Icon icon="material-symbols:bookmark-outline" width={40} />
<p className="text-base lg:text-lg">Simpan</p> <p className="text-base lg:text-lg">{t("save")}</p>
</a> </a>
)} )}
@ -276,7 +597,7 @@ const DetailDocument = () => {
<div className="border-t border-black my-4"></div> <div className="border-t border-black my-4"></div>
{/* Opsi Ukuran Foto */} {/* Opsi Ukuran Foto */}
<h4 className="flex text-lg justify-center items-center font-semibold my-3">Opsi Ukuran Foto</h4> <h4 className="flex text-lg justify-center items-center font-semibold my-3">{t("docSize")}</h4>
<div className="border-t border-black my-4"></div> <div className="border-t border-black my-4"></div>
<div className="space-y-2"> <div className="space-y-2">
{sizes.map((size: any) => ( {sizes.map((size: any) => (
@ -296,7 +617,7 @@ const DetailDocument = () => {
<div className="mt-4"> <div className="mt-4">
<label className="flex items-center space-x-2 text-sm"> <label className="flex items-center space-x-2 text-sm">
<input type="checkbox" className="text-red-600 focus:ring-red-600" onChange={() => setIsDownloadAll(!isDownloadAll)} /> <input type="checkbox" className="text-red-600 focus:ring-red-600" onChange={() => setIsDownloadAll(!isDownloadAll)} />
<span>Download Semua File?</span> <span>{t("downloadAll")}</span>
</label> </label>
</div> </div>
@ -305,19 +626,223 @@ const DetailDocument = () => {
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"> <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="white" d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z" /> <path fill="white" d="m12 16l-5-5l1.4-1.45l2.6 2.6V4h2v8.15l2.6-2.6L17 11zm-6 4q-.825 0-1.412-.587T4 18v-3h2v3h12v-3h2v3q0 .825-.587 1.413T18 20z" />
</svg> </svg>
Download {t("download")}
</button> </button>
{/* Tombol Bagikan */}
<div className="flex flex-row py-3">
<p className="text-base font-semibold">{t("share")}</p>
<a className="ml-8 cursor-pointer" onClick={() => handleShare("fb", `https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmediahub.polri.go.id%2F${typeString}%2Fdetail%2F${content?.id}&quote=${content?.title}`)}>
<Icon icon="brandico:facebook" height="20" className="px-auto text-red-600 text-center" />
</a>
<a className="ml-5 cursor-pointer" onClick={() => handleShare("tw", `https://twitter.com/share?url=https%3A%2F%2Fmediahub.polri.go.id%2F${typeString}%2Fdetail%2F${content?.id}&text=${content?.title}`)}>
<Icon icon="mdi:twitter" width="23" className="text-red-600 text-center" />
</a>
<a className="ml-5 cursor-pointer" onClick={() => handleShare("wa", `text=${content?.title}%0D%0A%0D%0Ahttps%3A%2F%2Fmediahub.polri.go.id%2F${typeString}%2Fdetail%2F${content?.id}`)}>
<Icon icon="ri:whatsapp-fill" width="23" className="text-red-600 text-center" />
</a>
<Popover>
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild>
<a className="ml-5 cursor-pointer" data-toggle="dropdown" href="#" aria-expanded="false">
<Icon icon="material-symbols-light:mail" width="23" className="text-red-600 text-center" />
</a>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
{t("send")}
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</div> </div>
</div> </div>
</div> </div>
<div className="w-full mb-8"> <div className="w-full mb-8">
{/* Comment */} {/* Comment */}
<div className="flex flex-col my-16 p-10 bg-[#f7f7f7]"> <div className="flex flex-col my-16 p-4 lg:p-10 bg-[#f7f7f7]">
<div className="gap-5 flex flex-col px-4 lg:px-16"> <div className="gap-5 flex flex-col px-4 lg:px-14">
<p className="flex items-start text-lg">Berikan Komentar</p> <p className="flex items-start text-lg">{t("comment")}</p>
<Textarea placeholder="Type your comments here." className="flex w-full" /> <Textarea placeholder="Type your comments here." className="flex w-full pb-12" onChange={getInputValue} />
<button className="flex items-start bg-[#bb3523] rounded-lg text-white w-fit px-4 py-1">Kirim</button> <button onClick={() => postData()} className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1">
{t("send")}
</button>
</div>
<div className="border-b-2 border-slate-300 mt-4 w-auto"></div>
<div>
{listSuggestion?.map((data: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:px-14">
<img src={data?.suggestionFrom?.profilePictureUrl} className="h-12 lg:h-16 w-12 lg:w-16 mr-2" onError={addDefaultProfile} alt="" />
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
{Number(data.suggestionFrom?.roleId) == 2 || Number(data.suggestionFrom?.roleId) == 3 || Number(data.suggestionFrom?.roleId) == 4 ? "HUMAS POLRI" : data.suggestionFrom?.fullname}
{getPublicLocaleTimestamp(new Date(data.createdAt))}
</p>
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">{data?.message}</p>
<div>
<a
style={
Number(data.suggestionFrom?.id) == Number(userId)
? {
display: "none",
}
: {}
}
onClick={() => showInput(`comment-id-${data.id}`)}
className="mr-2"
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("reply")}</small>
</a>
{Number(data.suggestionFrom?.id) == Number(userId) || Number(userRoleId) == 2 ? (
<a onClick={() => deleteData(data.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("delete")}</small>
</a>
) : (
""
)}
</div>
</div>
</div>
{visibleInput === `comment-id-${data.id}` && (
<div id={`comment-id-${data.id}`} className="px-4 pl-[72px] lg:px-14 lg:pl-32 mt-2 ">
<Textarea id={`input-comment-${data.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<div className="flex flex-row gap-3">
<a onClick={() => postDataChild(data.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 mt-2 cursor-pointer">{t("send")}</small>
</a>
<a onClick={() => showInput(`comment-id-${data.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg mt-2 w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("cancel")}</small>
</a>
</div>
</div>
)}
{data.children.length > 0
? data.children?.map((child1: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-16 lg:pl-32">
<img src={child1.suggestionFrom?.profilePictureUrl} onError={addDefaultProfile} alt="" className="h-10 lg:h-16 w-10 lg:w-16 mr-2" />
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
{" "}
<b>{Number(child1.suggestionFrom?.roleId) == 2 || Number(child1.suggestionFrom?.roleId) == 3 || Number(child1.suggestionFrom?.roleId) == 4 ? "HUMAS POLRI" : child1.suggestionFrom?.fullname}</b>{" "}
{getPublicLocaleTimestamp(new Date(child1.createdAt))}
</p>
<p className="text-slate-500 text-[13px] lg:text-sm mb-4">{parse(String(child1?.message))}</p>
<div>
<a
style={
Number(child1.suggestionFrom?.id) == Number(userId)
? {
display: "none",
}
: {}
}
onClick={() => showInput(`comment-id-${child1.id}`)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("reply")}</small>
</a>
<a
style={
Number(child1.suggestionFrom?.id) == Number(userId)
? {}
: {
display: "none",
}
}
onClick={() => deleteData(child1.id)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("delete")}</small>
</a>
</div>
</div>
</div>
{visibleInput === `comment-id-${child1.id}` && (
<div id={`comment-id-${child1.id}`} className="px-4 lg:px-14 pl-28 lg:pl-[200px]">
<Textarea name="" className="mt-2 " id={`input-comment-${child1.id}`} placeholder={t("enterReply")} />
<div className="flex flex-row mt-2 gap-3">
<a onClick={() => postDataChild(child1.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("send")}</small>
</a>
<a onClick={() => showInput(`comment-id-${child1.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("cancel")}</small>
</a>
</div>
</div>
)}
{child1.children.length > 0
? child1.children?.map((child2: any) => (
<div className="">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-28 lg:pl-48">
<img src={child2.suggestionFrom?.profilePictureUrl} className="h-9 lg:h-16 w-9 lg:w-16 mr-2" onError={addDefaultProfile} alt="" />
<div className="border border-slate-300 w-full p-2 lg:p-4 bg-white gap-1">
<p className="text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
{" "}
<b>{Number(child2.suggestionFrom?.roleId) == 2 || Number(child2.suggestionFrom?.roleId) == 3 || Number(child2.suggestionFrom?.roleId) == 4 ? "HUMAS POLRI" : child2.suggestionFrom?.fullname}</b>{" "}
{getPublicLocaleTimestamp(new Date(child2.createdAt))}
</p>
<p className="text-slate-500 text-sm mb-4">{parse(String(child2?.message))}</p>
<div>
<a
style={
Number(child2.suggestionFrom?.id) == Number(userId)
? {
display: "none",
}
: {}
}
onClick={() => showInput(`comment-id-${child2.id}`)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("reply")}</small>
</a>
<a
style={
Number(child2.suggestionFrom?.id) == Number(userId)
? {}
: {
display: "none",
}
}
onClick={() => deleteData(child2.id)}
>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("delete")}</small>
</a>
</div>
</div>
</div>
{visibleInput === `comment-id-${child2.id}` && (
<div id={`comment-id-${child2.id}`} className="px-4 lg:px-14 pl-40 lg:pl-[265px]">
<Textarea name="" id={`input-comment-${child2.id}`} className="my-2" placeholder={t("enterReply")} />
<div className="flex flex-row gap-3">
<a onClick={() => postDataChild(child2.id)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("send")}</small>
</a>
<a onClick={() => showInput(`comment-id-${child2.id}`)}>
<small className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-2 text-xs lg:text-base lg:px-4 py-1 cursor-pointer">{t("cancel")}</small>
</a>
</div>
</div>
)}
</div>
))
: ""}
</div>
))
: ""}
</div>
))}
</div> </div>
</div> </div>

View File

@ -17,7 +17,7 @@ import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals"; import { checkMaliciousText, formatDateToIndonesian, getPublicLocaleTimestamp } from "@/utils/globals";
import parse from "html-react-parser"; import parse from "html-react-parser";
import $ from "jquery"; import $ from "jquery";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
@ -594,12 +594,17 @@ const DetailAudio = () => {
<p className="text-xs lg:text-sm"> <p className="text-xs lg:text-sm">
{t("by")}&nbsp;<span className="font-semibold text-black">{detailDataAudio?.uploadedBy?.userLevel?.name}</span> {t("by")}&nbsp;<span className="font-semibold text-black">{detailDataAudio?.uploadedBy?.userLevel?.name}</span>
</p> </p>
<p className="text-xs lg:text-sm"> {/* <p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")} {detailDataAudio?.updatedAt} WIB &nbsp;|&nbsp; &nbsp;|&nbsp;{t("updatedOn")} {detailDataAudio?.updatedAt} WIB &nbsp;|&nbsp;
</p> */}
<p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")}&nbsp;
{formatDateToIndonesian(new Date(detailDataAudio?.updatedAt))} {"WIB"}
</p> </p>
<p className="text-xs lg:text-sm flex justify-center items-center"> <p className="text-xs lg:text-sm flex justify-center items-center">
&nbsp;| &nbsp;
<Icon icon="formkit:eye" width="15" height="15" /> <Icon icon="formkit:eye" width="15" height="15" />
&nbsp; {detailDataAudio?.clickCount} &nbsp; &nbsp;{detailDataAudio?.clickCount}&nbsp;
</p> </p>
</div> </div>
<div className="mt-3"> <div className="mt-3">
@ -611,7 +616,7 @@ const DetailAudio = () => {
{/* Keterangan */} {/* Keterangan */}
<div className="w-full"> <div className="w-full">
<h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8">{detailDataAudio?.title}</h1> <h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8">{detailDataAudio?.title}</h1>
<div className="font-light text-justify mb-5 lg:mb-0" dangerouslySetInnerHTML={{ __html: detailDataAudio?.htmlDescription }} /> <div className="font-light text-justify mb-5 lg:mb-0 space-y-4" dangerouslySetInnerHTML={{ __html: detailDataAudio?.htmlDescription }} />
</div> </div>
</div> </div>
@ -724,7 +729,7 @@ const DetailAudio = () => {
<p className="flex items-start text-lg">{t("comment")}</p> <p className="flex items-start text-lg">{t("comment")}</p>
<Textarea placeholder="Type your comments here." className="flex w-full pb-12" onChange={getInputValue} /> <Textarea placeholder="Type your comments here." className="flex w-full pb-12" onChange={getInputValue} />
<button onClick={() => postData()} className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1"> <button onClick={() => postData()} className="flex items-start bg-[#bb3523] rounded-lg w-fit text-white px-4 py-1">
{t("send")} {t("send")}
</button> </button>
</div> </div>

View File

@ -1,59 +1,159 @@
"use client"; "use client";
import { Reveal } from "@/components/landing-page/Reveal"; import { Reveal } from "@/components/landing-page/Reveal";
import React from "react"; import { getCookiesDecrypt } from "@/lib/utils";
import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup";
import { useForm } from "react-hook-form";
import { getInfoProfile, getProfile, getSubjects } from "@/service/auth";
import { close, error, loading, successCallback } from "@/config/swal";
import { sendMessage } from "@/service/landing/landing";
import { useTranslations } from "next-intl";
const ContactForm = () => { const ContactForm = () => {
const router = useRouter();
const userId = getCookiesDecrypt("uie");
const [subjects, setSubjects] = useState<any>();
const [isOtherActive, setIsOtherActive] = useState(false);
const t = useTranslations("LandingPage");
const form = document.getElementById("form") as HTMLFormElement;
// Form Handling
const validationSchema = Yup.object().shape({
name: Yup.string().required("Nama tidak boleh kosong"),
email: Yup.string().required("Email tidak boleh kosong"),
subjects: Yup.string().required("Subjek tidak boleh kosong"),
message: Yup.string().required("Pesan tidak boleh kosong"),
});
const formOptions = {
resolver: yupResolver(validationSchema),
};
const { register, handleSubmit, formState, setValue } = useForm(formOptions);
const { errors } = formState;
useEffect(() => {
async function initState() {
const response = await getInfoProfile();
const responseSubject = await getSubjects();
const profile = response?.data?.data;
setSubjects(responseSubject?.data?.data);
console.log(response);
setValue("name", profile?.fullname);
setValue("email", profile?.email); // setValue('name', profile?.fullname);
// setValue('name', profile?.fullname);
}
initState();
}, []);
async function save(data: any) {
loading();
const finalData = {
name: data.name,
email: data.email,
phone: data.phone,
title: isOtherActive ? data.othersubject : data.subjects,
message: data.message,
};
const response = await sendMessage(finalData);
if (response?.error) {
error(response?.message);
return false;
}
close();
successCallback("Terima kasih, pesan Anda telah terkirim");
// $("#form")[0].onreset();
if (form) {
form.reset();
}
}
async function onSubmit(data: any) {
if (userId == undefined) {
router.push("/auth/login");
} else {
save(data);
}
}
const handleSubjects = (e: any) => {
const id = e.target.value;
if (id == "Lainnya") {
setIsOtherActive(true);
} else {
setIsOtherActive(false);
}
};
return ( return (
<div className="max-w-2xl mx-auto bg-white p-6"> <form method="POST" id="form" onSubmit={handleSubmit(onSubmit)} className="max-w-2xl mx-auto bg-white p-6">
<Reveal> <Reveal>
{/* Header */} {/* Header */}
<div className="flex items-center justify-center mb-6"> <div className="flex items-center justify-center mb-6">
<img src="/assets/icons-contact.png" alt="contact" /> <img src="/assets/icons-contact.png" alt="contact" />
<h2 className="ml-4 text-2xl font-bold">Hubungi Kami</h2> <h2 className="ml-4 text-2xl font-bold">{t("contactUs")}</h2>
</div> </div>
<h3 className="text-lg font-semibold text-gray-800 mb-1">Tulis Pesan</h3> <h3 className="text-lg font-semibold text-gray-800 mb-1">{t("writeMessage")}</h3>
<p className="text-sm text-gray-600 mb-6">Silahkan tinggalkan pesan Anda pada kolom yang tersedia</p> <p className="text-sm text-gray-600 mb-6">{t("leaveMessage")}</p>
{/* Form */} {/* Form */}
<form> <form>
<div className="mb-4"> <div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-1">Nama</label> <label className="block text-sm font-medium text-gray-700 mb-1">{t("name")}</label>
<input type="text" placeholder="Masukkan nama lengkap Anda" className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required /> <input type="text" placeholder={t("enterName")} className={`w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.name ? "block" : ""}`} {...register("name")} required />
</div> </div>
<div className="mb-4"> <div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-1">Email</label> <label className="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input type="email" placeholder="name@mail.com" className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required /> <input type="email" placeholder="name@mail.com" className={`w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.email ? "block" : ""}`} {...register("email")} required />
</div> </div>
<div className="mb-4"> <div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-1">No. Handphone (Optional)</label> <label className="block text-sm font-medium text-gray-700 mb-1">{t("number")} (Optional)</label>
<input type="text" placeholder="Masukkan no.handphone" className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" /> <input type="text" placeholder={t("enterNumber")} className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
</div> </div>
<div className="mb-4"> <div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-1">Subjek</label> <label className="block text-sm font-medium text-gray-700 mb-1">{t("subject")}</label>
<select className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" defaultValue=""> <select
className={`w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.subjects ? "block" : ""}`}
{...register("subjects", { onChange: (e) => handleSubjects(e) })}
defaultValue=""
>
<option value="" disabled> <option value="" disabled>
Pilih Subjek {t("selectSubject")}
</option> </option>
<option value="1">Pertanyaan</option> {/* <option value="1">{t("question")}</option>
<option value="2">Kritik</option> <option value="2">{t("criticism")}</option>
<option value="3">Saran</option> <option value="3">{t("suggestion")}</option> */}
{subjects?.map((list: any) => (
<option key={list.id} value={list.title}>
{list.title}
</option>
))}
</select> </select>
</div> </div>
<div className="mb-4"> <div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-1">Pesan</label> <label className="block text-sm font-medium text-gray-700 mb-1">{t("messages")}</label>
<textarea placeholder="Tulis pesan Anda" rows={4} className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"></textarea> <textarea placeholder={t("writeYourMessage")} rows={4} className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"></textarea>
</div> </div>
<button type="submit" className="w-fit bg-blue-500 flex justify-self-end text-white p-2 px-8 rounded-md hover:bg-blue-600 transition"> <button type="submit" className="w-fit bg-blue-500 flex justify-self-end text-white p-2 px-8 rounded-md hover:bg-blue-600 transition">
Kirim {t("send")}
</button> </button>
</form> </form>
</Reveal> </Reveal>
</div> </form>
); );
}; };

View File

@ -5,7 +5,7 @@ import { checkWishlistStatus, deleteWishlist, getInfoProfile, mediaWishlist, sav
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Link, useRouter } from "@/i18n/routing"; import { Link, useRouter } from "@/i18n/routing";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useSearchParams } from "next/navigation"; import { usePathname, useSearchParams } from "next/navigation";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import HeaderManagement from "@/components/landing-page/header-management"; import HeaderManagement from "@/components/landing-page/header-management";
import SidebarManagement from "@/components/landing-page/sidebar-management"; import SidebarManagement from "@/components/landing-page/sidebar-management";
@ -19,6 +19,7 @@ import { Button } from "@/components/ui/button";
import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"; import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking";
import ImageBlurry from "@/components/ui/image-blurry"; import ImageBlurry from "@/components/ui/image-blurry";
import Image from "next/image"; import Image from "next/image";
import { useTranslations } from "next-intl";
const Galery = (props: any) => { const Galery = (props: any) => {
const [profile, setProfile] = useState<any>(); const [profile, setProfile] = useState<any>();
@ -26,6 +27,7 @@ const Galery = (props: any) => {
const router = useRouter(); const router = useRouter();
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const pathname = usePathname();
const page: any = searchParams?.get("page"); const page: any = searchParams?.get("page");
const title = searchParams?.get("title"); const title = searchParams?.get("title");
const category = searchParams?.get("category"); const category = searchParams?.get("category");
@ -50,6 +52,7 @@ const Galery = (props: any) => {
const [emailShareInput, setEmailShareInput] = useState<any>(); const [emailShareInput, setEmailShareInput] = useState<any>();
const [emailMessageInput, setEmailMessageInput] = useState(); const [emailMessageInput, setEmailMessageInput] = useState();
const id = searchParams?.get("id"); const id = searchParams?.get("id");
const t = useTranslations("LandingPage");
useEffect(() => { useEffect(() => {
getDataVideo(); getDataVideo();
@ -278,98 +281,117 @@ const Galery = (props: any) => {
<HeaderManagement /> <HeaderManagement />
<div className="flex flex-col lg:flex-row"> <div className="flex flex-col lg:flex-row">
<SidebarManagement /> <SidebarManagement />
<div className="w-full lg:w-2/3 p-8 lg:p-12"> <div className="w-full lg:w-2/3 p-8 lg:p-0 mt-12">
<div> <div className="flex flex-col mt-4">
<h1 className="text-2xl font-semibold mb-3">Galeri Saya</h1>
</div>
<div className="flex flex-col">
<div className="mx-auto w-full max-w-7xl justify-start flex flex-col lg:flex-row gap-5 mb-4"> <div className="mx-auto w-full max-w-7xl justify-start flex flex-col lg:flex-row gap-5 mb-4">
<h1 className="text-2xl w-fit font-bold bg-[#bb3523] px-4 py-1 rounded-lg text-center text-white">
{/* <span className="text-black">Galeri </span>
Saya */}
{pathname?.split("/")[1] == "in" ? (
<>
<span className="text-black ">{t("gallery")}</span>&nbsp;
{t("my")}
</>
) : (
<>
<span className="text-black">{t("my")}</span>&nbsp;
{t("gallery")}
</>
)}
</h1>
<Tabs value={selectedTab} onValueChange={setSelectedTab}> <Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabsList className="grid grid-cols-2 lg:flex lg:flex-row "> <TabsList className="grid grid-cols-2 lg:flex lg:flex-row ">
<TabsTrigger <TabsTrigger
value="image" value="image"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Foto {t("image")}
</TabsTrigger> </TabsTrigger>
<div className="text-[#bb3523] text-lg hidden md:inline-block">|</div> <div className="text-[#bb3523] text-lg hidden md:inline-block">|</div>
<TabsTrigger <TabsTrigger
value="video" value="video"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Audio Visual {t("video")}
</TabsTrigger> </TabsTrigger>
<div className="text-[#bb3523] text-lg hidden md:inline-block">|</div> <div className="text-[#bb3523] text-lg hidden md:inline-block">|</div>
<TabsTrigger <TabsTrigger
value="text" value="text"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Teks {t("text")}
</TabsTrigger> </TabsTrigger>
<div className="text-[#bb3523] text-lg hidden md:inline-block">|</div> <div className="text-[#bb3523] text-lg hidden md:inline-block">|</div>
<TabsTrigger <TabsTrigger
value="audio" value="audio"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Audio {t("audio")}
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
</Tabs> </Tabs>
</div> </div>
<div className=""> <div className="">
{selectedTab == "video" ? ( {selectedTab == "video" ? (
contentVideo?.length > 0 ? ( contentVideo?.length > 0 ? (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{contentVideo?.map((video: any) => ( {contentVideo?.map((video: any) => (
<Card key={video?.id}> <Card key={video?.id} className="hover:scale-105 transition-transform duration-300">
<CardContent className="flex flex-col bg-black dark:bg-white w-full rounded-lg p-0"> <CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<div> <div>
<Link href={`/video/detail/${video?.mediaUpload?.slug}`}> <div className="relative group overflow-hidden shadow-md hover:shadow-lg">
{/* <img src={video?.mediaUpload?.thumbnailLink} className="h-40 object-cover items-center justify-center cursor-pointer rounded-lg " /> */} <div className="relative h-60 rounded-lg overflow-hidden">
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg"> <ImageBlurry src={video?.mediaUpload?.thumbnailLink} alt={video?.mediaUpload?.title} style={{ objectFit: "cover", width: "100%", height: "100%" }} />
<ImageBlurry src={video?.mediaUpload?.thumbnailLink} alt={video?.mediaUpload?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} /> <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-transparent via-gray-900/80 to-transparent text-white">
</div> <Link href={`/video/detail/${video?.mediaUpload?.slug}`}>
</Link> <p className="text-sm p-2 lg:text-base font-semibold truncate">{video?.mediaUpload?.title}</p>
<div className="font-semibold p-4 text-white text-xs lg:text-sm dark:text-black truncate w-full">{video?.mediaUpload?.title}</div> </Link>
<Popover> <p className="flex text-[10px] ml-1 mb-2 items-end">
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild> <Popover>
<a className="flex justify-end items-end place-items-end"> <PopoverTrigger className="flex cursor-pointer" asChild>
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" /> <a className="flex justify-end items-end place-items-end">
</a> <Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
</PopoverTrigger> </a>
<PopoverContent className="w-52"> </PopoverTrigger>
<Link href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2"> <PopoverContent className="w-52">
<Icon icon="jam:write" fontSize={25} /> <div onClick={() => handleSaveWishlist(video?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<p className="text-base font-semibold mb-2">Content Rewrite</p> <Icon icon="material-symbols:bookmark-outline" fontSize={25} />
</Link> <p className="text-base font-semibold mb-2">{t("save")}</p>
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
<Popover>
<PopoverTrigger asChild>
<button className="w-full flex items-center gap-3">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-3">Bagikan</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Link href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
Kirim <Icon icon="jam:write" fontSize={25} />
</Button> <p className="text-base font-semibold mb-2">Content Rewrite</p>
</div> </Link>
</PopoverContent> <div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
</Popover> <Popover>
<PopoverTrigger asChild>
<button className="w-full flex flex-row items-center gap-3">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-1">{t("share")}</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
{t("send")}
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</PopoverContent>
</Popover>
</p>
</div> </div>
<a onClick={() => handleDelete(video?.id)} className="flex items-center gap-3 hover:text-red-800 w-full rounded-lg"> </div>
<Icon icon="fa:trash" fontSize={20} /> </div>
<p className="text-base font-semibold">Hapus</p>
</a>
</PopoverContent>
</Popover>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
@ -414,12 +436,16 @@ const Galery = (props: any) => {
</div> </div>
</div> </div>
<Popover> <Popover>
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild> <PopoverTrigger className="flex cursor-pointer" asChild>
<a className="flex justify-end items-end place-items-end"> <a className="flex justify-end items-end place-items-end">
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" /> <Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
</a> </a>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-52"> <PopoverContent className="w-52">
<div onClick={() => handleSaveWishlist(audio?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<p className="text-base font-semibold mb-2">{t("save")}</p>
</div>
<Link href={`/content-management/rewrite/create/${audio?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2"> <Link href={`/content-management/rewrite/create/${audio?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} /> <Icon icon="jam:write" fontSize={25} />
<p className="text-base font-semibold mb-2">Content Rewrite</p> <p className="text-base font-semibold mb-2">Content Rewrite</p>
@ -427,29 +453,25 @@ const Galery = (props: any) => {
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg"> <div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
<Popover> <Popover>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<button className="w-full flex items-center gap-3"> <button className="w-full flex flex-row items-center gap-3">
<Icon icon="oi:share" fontSize={20} /> <Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-3">Bagikan</p> <p className="text-base font-semibold mb-1">{t("share")}</p>
</button> </button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent> <PopoverContent>
<div className="flex flex-col"> <div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1> <h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2"> <div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p> <p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" /> <Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
Kirim {t("send")}
</Button> </Button>
</div> </div>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>
<a onClick={() => handleDelete(audio?.id)} className="flex items-center gap-3 hover:text-red-800 w-full rounded-lg">
<Icon icon="fa:trash" fontSize={20} />
<p className="text-base font-semibold">Hapus</p>
</a>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>
@ -464,54 +486,61 @@ const Galery = (props: any) => {
contentImage?.length > 0 ? ( contentImage?.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{contentImage?.map((image: any) => ( {contentImage?.map((image: any) => (
<Card key={image?.id}> <Card key={image?.id} className="hover:scale-105 transition-transform duration-300">
<CardContent className="flex flex-col bg-black dark:bg-white w-full h-full rounded-lg p-0"> <CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<Link href={`/image/detail/${image?.mediaUpload?.slug}`}> <div>
{/* <img src={image?.mediaUpload?.thumbnailLink} className="h-40 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */} <div className="relative group overflow-hidden shadow-md hover:shadow-lg">
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg"> <div className="relative h-60 rounded-lg overflow-hidden">
<ImageBlurry src={image?.mediaUpload?.thumbnailLink} alt={image?.mediaUpload?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} /> <ImageBlurry src={image?.mediaUpload?.thumbnailLink} alt={image?.mediaUpload?.title} style={{ objectFit: "cover", width: "100%", height: "100%" }} />
</div> <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-transparent via-gray-900/80 to-transparent text-white">
</Link> <Link href={`/video/detail/${image?.mediaUpload?.slug}`}>
<div className="font-semibold p-4 text-white text-xs lg:text-sm dark:text-black truncate w-full">{image?.mediaUpload?.title}</div> <p className="text-sm p-2 lg:text-base font-semibold truncate">{image?.mediaUpload?.title}</p>
<Popover> </Link>
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild> <p className="flex text-[10px] ml-1 mb-2 items-end">
<a className="flex justify-end items-end place-items-end"> <Popover>
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" /> <PopoverTrigger className="flex cursor-pointer" asChild>
</a> <a className="flex justify-end items-end place-items-end">
</PopoverTrigger> <Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
<PopoverContent className="w-52"> </a>
<Link href={`/content-management/rewrite/create/${image?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2"> </PopoverTrigger>
<Icon icon="jam:write" fontSize={25} /> <PopoverContent className="w-52">
<p className="text-base font-semibold mb-2">Content Rewrite</p> <div onClick={() => handleSaveWishlist(image?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
</Link> <Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg"> <p className="text-base font-semibold mb-2">{t("save")}</p>
<Popover> </div>
<PopoverTrigger asChild> <Link href={`/content-management/rewrite/create/${image?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<button className="w-full flex items-center gap-3"> <Icon icon="jam:write" fontSize={25} />
<Icon icon="oi:share" fontSize={20} /> <p className="text-base font-semibold mb-2">Content Rewrite</p>
<p className="text-base font-semibold mb-3">Bagikan</p> </Link>
</button> <div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
</PopoverTrigger> <Popover>
<PopoverContent> <PopoverTrigger asChild>
<div className="flex flex-col"> <button className="w-full flex flex-row items-center gap-3">
<h1 className="mb-2">Share Ke Email</h1> <Icon icon="oi:share" fontSize={20} />
<div className="flex flex-col mb-2"> <p className="text-base font-semibold mb-1"> {t("share")}</p>
<p className="text-base font-semibold mb-1">Email Tujuan :</p> </button>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" /> </PopoverTrigger>
</div> <PopoverContent>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <div className="flex flex-col">
Kirim <h1 className="mb-2">{t("shareTo")}</h1>
</Button> <div className="flex flex-col mb-2">
</div> <p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
</PopoverContent> <Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</Popover> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
{t("send")}
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</PopoverContent>
</Popover>
</p>
</div>
</div> </div>
<a onClick={() => handleDelete(image?.id)} className="flex items-center gap-3 hover:text-red-800 w-full rounded-lg"> </div>
<Icon icon="fa:trash" fontSize={20} /> </div>
<p className="text-base font-semibold">Hapus</p>
</a>
</PopoverContent>
</Popover>
</CardContent> </CardContent>
</Card> </Card>
))} ))}
@ -542,7 +571,7 @@ const Galery = (props: any) => {
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"> <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512">
<path fill="#f00" d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z" /> <path fill="#f00" d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z" />
</svg> </svg>
Download Dokumen Download {t("document")}
</div> </div>
</div> </div>
<Popover> <Popover>
@ -552,6 +581,10 @@ const Galery = (props: any) => {
</a> </a>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-52"> <PopoverContent className="w-52">
<div onClick={() => handleSaveWishlist(document?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<p className="text-base font-semibold mb-2">{t("save")}</p>
</div>
<Link href={`/content-management/rewrite/create/${document?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2"> <Link href={`/content-management/rewrite/create/${document?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} /> <Icon icon="jam:write" fontSize={25} />
<p className="text-base font-semibold mb-2">Content Rewrite</p> <p className="text-base font-semibold mb-2">Content Rewrite</p>
@ -559,29 +592,25 @@ const Galery = (props: any) => {
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg"> <div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
<Popover> <Popover>
<PopoverTrigger asChild> <PopoverTrigger asChild>
<button className="w-full flex items-center gap-3"> <button className="w-full flex items-center gap-2">
<Icon icon="oi:share" fontSize={20} /> <Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-3">Bagikan</p> <p className="text-base font-semibold mb-2">{t("share")}</p>
</button> </button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent> <PopoverContent>
<div className="flex flex-col"> <div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1> <h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2"> <div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p> <p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" /> <Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
Kirim {t("send")}
</Button> </Button>
</div> </div>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>
<a onClick={() => handleDelete(document?.id)} className="flex items-center gap-3 hover:text-red-800 w-full rounded-lg">
<Icon icon="fa:trash" fontSize={20} />
<p className="text-base font-semibold">Hapus</p>
</a>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>

View File

@ -21,6 +21,7 @@ import { Button } from "@/components/ui/button";
import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"; import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking";
import ImageBlurry from "@/components/ui/image-blurry"; import ImageBlurry from "@/components/ui/image-blurry";
import Image from "next/image"; import Image from "next/image";
import { useTranslations } from "next-intl";
const Galery = (props: any) => { const Galery = (props: any) => {
const [profile, setProfile] = useState<any>(); const [profile, setProfile] = useState<any>();
@ -53,6 +54,7 @@ const Galery = (props: any) => {
const [emailShareInput, setEmailShareInput] = useState<any>(); const [emailShareInput, setEmailShareInput] = useState<any>();
const [emailMessageInput, setEmailMessageInput] = useState(); const [emailMessageInput, setEmailMessageInput] = useState();
const id = searchParams?.get("id"); const id = searchParams?.get("id");
const t = useTranslations("LandingPage");
useEffect(() => { useEffect(() => {
getDataVideo(); getDataVideo();
@ -284,98 +286,105 @@ const Galery = (props: any) => {
<HeaderManagement /> <HeaderManagement />
<div className="flex flex-col lg:flex-row"> <div className="flex flex-col lg:flex-row">
<SidebarManagement /> <SidebarManagement />
<div className="w-full lg:w-2/3 p-8 lg:p-12"> <div className="w-full lg:w-2/3 p-8 lg:p-0 mt-12">
<div>
<h1 className="text-2xl font-semibold">Galeri {profile?.institute?.name}</h1>
</div>
<div className="flex flex-col mt-4"> <div className="flex flex-col mt-4">
<div className="mx-auto w-full max-w-7xl justify-start flex flex-col lg:flex-row gap-5 mb-4"> <div className="mx-auto w-full max-w-7xl justify-start flex flex-col lg:flex-row gap-5 mb-4">
<h1 className="text-2xl w-fit font-bold bg-[#bb3523] px-4 py-1 rounded-lg text-center text-white">
<span className="text-black">{t("gallery")} </span>
{profile?.institute?.name}
</h1>
<Tabs value={selectedTab} onValueChange={setSelectedTab}> <Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabsList className="grid grid-cols-2 lg:flex lg:flex-row "> <TabsList className="grid grid-cols-2 lg:flex lg:flex-row ">
<TabsTrigger <TabsTrigger
value="image" value="image"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Foto {t("image")}
</TabsTrigger> </TabsTrigger>
<div className="text-[#bb3523] text-lg hidden md:inline-block">|</div> <div className="text-[#bb3523] text-lg hidden md:inline-block">|</div>
<TabsTrigger <TabsTrigger
value="video" value="video"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Audio Visual {t("video")}
</TabsTrigger> </TabsTrigger>
<div className="text-[#bb3523] text-lg hidden md:inline-block">|</div> <div className="text-[#bb3523] text-lg hidden md:inline-block">|</div>
<TabsTrigger <TabsTrigger
value="text" value="text"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Teks {t("text")}
</TabsTrigger> </TabsTrigger>
<div className="text-[#bb3523] text-lg hidden md:inline-block">|</div> <div className="text-[#bb3523] text-lg hidden md:inline-block">|</div>
<TabsTrigger <TabsTrigger
value="audio" value="audio"
className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary" className="relative text-xs md:text-xl font-bold text-black dark:text-white dark:bg-transparent before:absolute before:top-full before:left-0 before:h-px before:w-full data-[state=active]:before:bg-primary"
> >
Audio {t("audio")}
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
</Tabs> </Tabs>
</div> </div>
<div className="px-2"> <div className="px-2">
{selectedTab == "video" ? ( {selectedTab == "video" ? (
contentVideo?.length > 0 ? ( contentVideo?.length > 0 ? (
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{contentVideo?.map((video: any) => ( {contentVideo?.map((video: any) => (
<Card key={video?.id}> <Card key={video?.id} className="hover:scale-105 transition-transform duration-300">
<CardContent className="flex flex-col bg-black dark:bg-white w-full rounded-lg p-0"> <CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<div> <div>
<Link href={`/video/detail/${video?.mediaUpload?.slug}`}> <div className="relative group overflow-hidden shadow-md hover:shadow-lg">
{/* <img src={video?.mediaUpload?.thumbnailLink} className="h-40 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */} <div className="relative h-60 rounded-lg overflow-hidden">
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg"> <ImageBlurry src={video?.mediaUpload?.thumbnailLink} alt={video?.mediaUpload?.title} style={{ objectFit: "cover", width: "100%", height: "100%" }} />
<ImageBlurry src={video?.mediaUpload?.thumbnailLink} alt={video?.mediaUpload?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} /> <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-transparent via-gray-900/80 to-transparent text-white">
</div> <Link href={`/video/detail/${video?.mediaUpload?.slug}`}>
</Link> <p className="text-sm p-2 lg:text-base font-semibold truncate">{video?.mediaUpload?.title}</p>
<div className="font-semibold p-4 text-white text-xs lg:text-sm dark:text-black truncate w-full">{video?.mediaUpload?.title}</div> </Link>
<Popover> <p className="flex text-[10px] ml-1 mb-2 items-end">
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild> <Popover>
<a className="flex justify-end items-end place-items-end"> <PopoverTrigger className="flex cursor-pointer" asChild>
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" /> <a className="flex justify-end items-end place-items-end">
</a> <Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
</PopoverTrigger> </a>
<PopoverContent className="w-52"> </PopoverTrigger>
<div onClick={() => handleSaveWishlist(video?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800"> <PopoverContent className="w-52">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} /> <div onClick={() => handleSaveWishlist(video?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<p className="text-base font-semibold mb-2">Simpan</p> <Icon icon="material-symbols:bookmark-outline" fontSize={25} />
</div> <p className="text-base font-semibold mb-2">{t("save")} </p>
<Link href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} />
<p className="text-base font-semibold mb-2">Content Rewrite</p>
</Link>
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
<Popover>
<PopoverTrigger asChild>
<button className="w-full flex flex-row items-center gap-3">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-1">Bagikan</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Link href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
Kirim <Icon icon="jam:write" fontSize={25} />
</Button> <p className="text-base font-semibold mb-2">Content Rewrite</p>
</div> </Link>
</PopoverContent> <div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
</Popover> <Popover>
<PopoverTrigger asChild>
<button className="w-full flex flex-row items-center gap-3">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-1">{t("share")} </p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">{t("shareTo")} </h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("shareTo")} />
</div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
{t("send")}
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</PopoverContent>
</Popover>
</p>
</div> </div>
</PopoverContent> </div>
</Popover> </div>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
@ -426,7 +435,7 @@ const Galery = (props: any) => {
<PopoverContent className="w-52"> <PopoverContent className="w-52">
<div onClick={() => handleSaveWishlist(audio?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800"> <div onClick={() => handleSaveWishlist(audio?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} /> <Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<p className="text-base font-semibold mb-2">Simpan</p> <p className="text-base font-semibold mb-2">{t("save")}</p>
</div> </div>
<Link href={`/content-management/rewrite/create/${audio?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2"> <Link href={`/content-management/rewrite/create/${audio?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} /> <Icon icon="jam:write" fontSize={25} />
@ -437,18 +446,18 @@ const Galery = (props: any) => {
<PopoverTrigger asChild> <PopoverTrigger asChild>
<button className="w-full flex items-center gap-2"> <button className="w-full flex items-center gap-2">
<Icon icon="oi:share" fontSize={20} /> <Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-2">Bagikan</p> <p className="text-base font-semibold mb-2">{t("share")}</p>
</button> </button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent> <PopoverContent>
<div className="flex flex-col"> <div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1> <h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2"> <div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p> <p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" /> <Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
Kirim {t("send")}
</Button> </Button>
</div> </div>
</PopoverContent> </PopoverContent>
@ -468,54 +477,61 @@ const Galery = (props: any) => {
contentImage?.length > 0 ? ( contentImage?.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{contentImage?.map((image: any) => ( {contentImage?.map((image: any) => (
<Card key={image?.id}> <Card key={image?.id} className="hover:scale-105 transition-transform duration-300">
<CardContent className="flex flex-col bg-black dark:bg-white w-full rounded-lg p-0"> <CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<Link href={`/image/detail/${image?.mediaUpload?.slug}`}> <div>
{/* <img src={image?.mediaUpload?.thumbnailLink} className="h-40 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */} <div className="relative group overflow-hidden shadow-md hover:shadow-lg">
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg"> <div className="relative h-60 rounded-lg overflow-hidden">
<ImageBlurry src={image?.mediaUpload?.thumbnailLink} alt={image?.mediaUpload?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} /> <ImageBlurry src={image?.mediaUpload?.thumbnailLink} alt={image?.mediaUpload?.title} style={{ objectFit: "cover", width: "100%", height: "100%" }} />
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-transparent via-gray-900/80 to-transparent text-white">
<Link href={`/video/detail/${image?.mediaUpload?.slug}`}>
<p className="text-sm p-2 lg:text-base font-semibold truncate">{image?.mediaUpload?.title}</p>
</Link>
<p className="flex text-[10px] ml-1 mb-2 items-end">
<Popover>
<PopoverTrigger className="flex cursor-pointer" asChild>
<a className="flex justify-end items-end place-items-end">
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
</a>
</PopoverTrigger>
<PopoverContent className="w-52">
<div onClick={() => handleSaveWishlist(image?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<p className="text-base font-semibold mb-2">{t("save")}</p>
</div>
<Link href={`/content-management/rewrite/create/${image?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} />
<p className="text-base font-semibold mb-2">Content Rewrite</p>
</Link>
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
<Popover>
<PopoverTrigger asChild>
<button className="w-full flex flex-row items-center gap-3">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-1"> {t("share")}</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
{t("send")}
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</PopoverContent>
</Popover>
</p>
</div>
</div>
</div> </div>
</Link> </div>
<div className="font-semibold p-4 text-white text-xs lg:text-sm dark:text-black truncate w-full">{image?.mediaUpload?.title}</div>
<Popover>
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild>
<a className="flex justify-end items-end place-items-end">
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
</a>
</PopoverTrigger>
<PopoverContent className="w-52">
<div onClick={() => handleSaveWishlist(image?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<p className="text-base font-semibold mb-2">Simpan</p>
</div>
<Link href={`/content-management/rewrite/create/${image?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} />
<p className="text-base font-semibold mb-2">Content Rewrite</p>
</Link>
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
<Popover>
<PopoverTrigger asChild>
<button className="w-full flex items-center gap-2">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-2">Bagikan</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" />
</div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
Kirim
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</PopoverContent>
</Popover>
</CardContent> </CardContent>
</Card> </Card>
))} ))}
@ -546,7 +562,7 @@ const Galery = (props: any) => {
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"> <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512">
<path fill="#f00" d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z" /> <path fill="#f00" d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z" />
</svg> </svg>
Download Dokumen Download {t("document")}
</div> </div>
</div> </div>
<Popover> <Popover>
@ -558,7 +574,7 @@ const Galery = (props: any) => {
<PopoverContent className="w-52"> <PopoverContent className="w-52">
<div onClick={() => handleSaveWishlist(document?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800"> <div onClick={() => handleSaveWishlist(document?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<Icon icon="material-symbols:bookmark-outline" fontSize={25} /> <Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<p className="text-base font-semibold mb-2">Simpan</p> <p className="text-base font-semibold mb-2">{t("save")}</p>
</div> </div>
<Link href={`/content-management/rewrite/create/${document?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2"> <Link href={`/content-management/rewrite/create/${document?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
<Icon icon="jam:write" fontSize={25} /> <Icon icon="jam:write" fontSize={25} />
@ -569,18 +585,18 @@ const Galery = (props: any) => {
<PopoverTrigger asChild> <PopoverTrigger asChild>
<button className="w-full flex items-center gap-2"> <button className="w-full flex items-center gap-2">
<Icon icon="oi:share" fontSize={20} /> <Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-2">Bagikan</p> <p className="text-base font-semibold mb-2">{t("share")}</p>
</button> </button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent> <PopoverContent>
<div className="flex flex-col"> <div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1> <h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2"> <div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p> <p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" /> <Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
Kirim {t("send")}
</Button> </Button>
</div> </div>
</PopoverContent> </PopoverContent>

View File

@ -21,10 +21,10 @@ import { getPublicSuggestionList } from "@/service/landing/landing";
import { getDetail } from "@/service/detail/detail"; import { getDetail } from "@/service/detail/detail";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import * as Yup from "yup"; import * as Yup from "yup";
import { htmlToString } from "@/utils/globals";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { useTranslations } from "next-intl";
const imageSchema = z.object({ const imageSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
@ -63,6 +63,7 @@ const page = (props: any) => {
const [isLoadingData, setIsLoadingData] = useState<boolean>(false); const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
const [detailData, setDetailData] = useState<any>(null); const [detailData, setDetailData] = useState<any>(null);
const [articleImages, setArticleImages] = useState<string[]>([]); const [articleImages, setArticleImages] = useState<string[]>([]);
const t = useTranslations("LandingPage");
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");
const roleId = getCookiesDecrypt("urie"); const roleId = getCookiesDecrypt("urie");
@ -293,21 +294,21 @@ const page = (props: any) => {
<SidebarManagement /> <SidebarManagement />
<div className="w-full lg:w-2/3 p-8 lg:p-12"> <div className="w-full lg:w-2/3 p-8 lg:p-12">
<div className="flex flex-col"> <div className="flex flex-col">
<div className="text-xl font-bold mb-5">Content Rewrite</div> <div className="text-xl font-bold mb-5">{t("content")} Rewrite</div>
<div className="p-8 border border-black rounded-lg"> <div className="p-8 border border-black rounded-lg">
<form method="POST" onSubmit={handleSubmit(onSubmit)}> <form method="POST" onSubmit={handleSubmit(onSubmit)}>
{content && ( {content && (
<div className="flex flex-col gap-2 "> <div className="flex flex-col gap-2 ">
<div className="flex flex-col lg:flex-row gap-2"> <div className="flex flex-col lg:flex-row gap-2">
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Bahasa</p> <p className="font-semibold">{t("language")}</p>
<Select value={selectedLanguage} onValueChange={setSelectedLanguage}> <Select value={selectedLanguage} onValueChange={setSelectedLanguage}>
<SelectTrigger className="w-full lg:w-[180px]"> <SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder="Pilih Bahasa" /> <SelectValue placeholder={t("selectLanguage")} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
<SelectLabel>Pilih Bahasa</SelectLabel> <SelectLabel>{t("selectLanguage")}</SelectLabel>
<SelectItem value="id">Indonesia</SelectItem> <SelectItem value="id">Indonesia</SelectItem>
<SelectItem value="en">English</SelectItem> <SelectItem value="en">English</SelectItem>
</SelectGroup> </SelectGroup>
@ -315,31 +316,31 @@ const page = (props: any) => {
</Select> </Select>
</div> </div>
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Context Type</p> <p className="font-semibold">{t("contextType")}</p>
<Select value={selectedContextType} onValueChange={setSelectedContextType}> <Select value={selectedContextType} onValueChange={setSelectedContextType}>
<SelectTrigger className="w-full lg:w-[180px]"> <SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder="Select Context" /> <SelectValue placeholder={t("selectContext")} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
<SelectLabel>Select Context Type</SelectLabel> <SelectLabel>{t("selectContext")}</SelectLabel>
<SelectItem value="text">Text</SelectItem> <SelectItem value="text">{t("text")}</SelectItem>
<SelectItem value="article">Article</SelectItem> <SelectItem value="article">{t("article")}</SelectItem>
<SelectItem value="transcript">Transcript</SelectItem> <SelectItem value="transcript">{t("transcript")}</SelectItem>
<SelectItem value="url">URL</SelectItem> <SelectItem value="url">URL</SelectItem>
</SelectGroup> </SelectGroup>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Writing Style</p> <p className="font-semibold">{t("writingStyle")}</p>
<Select value={selectedWritingStyle} onValueChange={setSelectedWritingStyle}> <Select value={selectedWritingStyle} onValueChange={setSelectedWritingStyle}>
<SelectTrigger className="w-full lg:w-[180px]"> <SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder="Select Writing" /> <SelectValue placeholder={t("selectWriting")} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
<SelectLabel>Select Writing Style</SelectLabel> <SelectLabel>{t("selectWriting")}</SelectLabel>
<SelectItem value="firendly">Friendly</SelectItem> <SelectItem value="firendly">Friendly</SelectItem>
<SelectItem value="profesional">Profesional</SelectItem> <SelectItem value="profesional">Profesional</SelectItem>
<SelectItem value="informational">Informational</SelectItem> <SelectItem value="informational">Informational</SelectItem>
@ -350,14 +351,14 @@ const page = (props: any) => {
</Select> </Select>
</div> </div>
<div className="gap-1 flex flex-col mb-3"> <div className="gap-1 flex flex-col mb-3">
<p className="font-semibold">Article Size</p> <p className="font-semibold">{t("articleSize")}</p>
<Select value={selectedSize} onValueChange={setSelectedSize}> <Select value={selectedSize} onValueChange={setSelectedSize}>
<SelectTrigger className="w-full lg:w-[180px]"> <SelectTrigger className="w-full lg:w-[180px]">
<SelectValue placeholder="Select Size" /> <SelectValue placeholder={t("selectSize")} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
<SelectLabel>Select Article Size</SelectLabel> <SelectLabel>{t("selectSize")}</SelectLabel>
<SelectItem value="news">News (300 - 900 words)</SelectItem> <SelectItem value="news">News (300 - 900 words)</SelectItem>
<SelectItem value="info">Info (900 - 2000 words)</SelectItem> <SelectItem value="info">Info (900 - 2000 words)</SelectItem>
<SelectItem value="detail">Detail (2000 - 5000 words)</SelectItem> <SelectItem value="detail">Detail (2000 - 5000 words)</SelectItem>
@ -367,7 +368,7 @@ const page = (props: any) => {
</div> </div>
</div> </div>
<div className="mb-3"> <div className="mb-3">
<p className="font-semibold">Judul</p> <p className="font-semibold">{t("title")}</p>
<Controller <Controller
control={control} control={control}
name="title" name="title"
@ -375,7 +376,7 @@ const page = (props: any) => {
/> />
</div> </div>
<div className="mb-3"> <div className="mb-3">
<p className="font-semibold">Main Keyword</p> <p className="font-semibold">{t("mainKeyword")}</p>
<Controller <Controller
control={control} control={control}
name="mainKeyword" name="mainKeyword"
@ -418,7 +419,7 @@ const page = (props: any) => {
</div> </div>
<div className=" mb-3"> <div className=" mb-3">
<p className="font-semibold">Deskripsi Baru</p> <p className="font-semibold">{t("newDescription")}</p>
<Controller <Controller
control={control} control={control}
name="description" name="description"
@ -442,10 +443,10 @@ const page = (props: any) => {
}} }}
className="border border-blue-400 hover:bg-blue-400 hover:text-white text-blue-400 text-sm lg:text-base" className="border border-blue-400 hover:bg-blue-400 hover:text-white text-blue-400 text-sm lg:text-base"
> >
Kembali {t("back")}
</Button> </Button>
<Button type="submit" className="border border-blue-500 bg-blue-500 text-sm lg:text-base text-white"> <Button type="submit" className="border border-blue-500 bg-blue-500 text-sm lg:text-base text-white">
Simpan {t("save")}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -34,15 +34,12 @@ const page = () => {
const userRoleId = getCookiesDecrypt("urie"); const userRoleId = getCookiesDecrypt("urie");
const [articleIds, setArticleIds] = useState<any>([]); const [articleIds, setArticleIds] = useState<any>([]);
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false); const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
const [selectedArticleId, setSelectedArticleId] = useState(null);
const [articleBody, setArticleBody] = useState<any>(""); const [articleBody, setArticleBody] = useState<any>("");
const [selectedAdvConfig, setSelectedAdvConfig] = useState(""); const [selectedAdvConfig, setSelectedAdvConfig] = useState("");
const [selectedWritingStyle, setSelectedWritingStyle] = useState(""); const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
const [selectedContextType, setSelectedContextType] = useState(""); const [selectedContextType, setSelectedContextType] = useState("");
const [selectedLanguage, setSelectedLanguage] = useState(""); const [selectedLanguage, setSelectedLanguage] = useState("");
const [selectedTitle, setSelectedTitle] = useState("");
const [selectedMainKeyword, setSelectedMainKeyword] = useState(""); const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
const [selectedSEO, setSelectedSEO] = useState("");
const [selectedSize, setSelectedSize] = useState(""); const [selectedSize, setSelectedSize] = useState("");
const [detailArticle, setDetailArticle] = useState<any>(null); const [detailArticle, setDetailArticle] = useState<any>(null);
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");

View File

@ -18,6 +18,7 @@ import { Button } from "@/components/ui/button";
import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"; import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking";
import ImageBlurry from "@/components/ui/image-blurry"; import ImageBlurry from "@/components/ui/image-blurry";
import Image from "next/image"; import Image from "next/image";
import { useTranslations } from "next-intl";
const page = () => { const page = () => {
const [, setProfile] = useState(); const [, setProfile] = useState();
@ -43,6 +44,7 @@ const page = () => {
const [emailShareInput, setEmailShareInput] = useState<any>(); const [emailShareInput, setEmailShareInput] = useState<any>();
const [emailMessageInput, setEmailMessageInput] = useState(); const [emailMessageInput, setEmailMessageInput] = useState();
const id = searchParams?.get("id"); const id = searchParams?.get("id");
const t = useTranslations("LandingPage");
useEffect(() => { useEffect(() => {
async function initState() { async function initState() {
@ -200,59 +202,69 @@ const page = () => {
<HeaderManagement /> <HeaderManagement />
<div className="flex flex-col lg:flex-row"> <div className="flex flex-col lg:flex-row">
<SidebarManagement /> <SidebarManagement />
<div className="w-full lg:w-2/3 p-8 lg:p-12"> <div className="w-full lg:w-2/3 p-8 lg:p-14">
<div> <h1 className="text-2xl w-fit font-bold bg-[#bb3523] px-4 py-1 rounded-lg text-center text-white mb-4">
<h1 className="text-2xl font-semibold mb-4">Galeri Content Rewrite</h1> <span className="text-black">{t("gallery")} </span>
</div> {t("content")} Rewrite
</h1>
<div className=""> <div className="">
{contentImage?.length > 0 ? ( {contentImage?.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{contentImage?.map((image: any) => ( {contentImage?.map((image: any) => (
<Card key={image?.id}> <Card key={image?.id} className="hover:scale-105 transition-transform duration-300">
<CardContent className="flex flex-col bg-black dark:bg-white w-full rounded-lg p-0"> <CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<div className=""> <div>
<Link href={`/content-management/rewrite/detail/${image.id}`}> <div className="relative group overflow-hidden shadow-md hover:shadow-lg">
{/* <img src={image?.thumbnailUrl} className="h-40 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */} <div className="relative h-60 rounded-lg overflow-hidden">
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
<ImageBlurry src={image?.thumbnailUrl} alt={image?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} /> <ImageBlurry src={image?.thumbnailUrl} alt={image?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} />
</div> <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-transparent via-gray-900/80 to-transparent text-white">
</Link> <Link href={`/content-management/rewrite/detail/${image.id}`}>
<div className="font-semibold p-4 text-white text-xs lg:text-sm dark:text-black truncate w-full">{image?.title}</div> <p className="text-sm p-2 lg:text-base font-semibold truncate">{image?.title}</p>
<Popover> </Link>
<PopoverTrigger className="flex justify-end gap-1 cursor-pointer" asChild> <p className="flex text-[10px] ml-1 mb-2 items-end">
<a className="flex justify-end items-end place-items-end"> <Popover>
<Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" /> <PopoverTrigger className="flex cursor-pointer" asChild>
</a> <a className="flex justify-end items-end place-items-end">
</PopoverTrigger> <Icon className="text-white ml-1" fontSize={25} icon="tabler:dots" />
<PopoverContent className="w-40"> </a>
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg"> </PopoverTrigger>
<Popover> <PopoverContent className="w-52">
<PopoverTrigger asChild> <div onClick={() => handleSaveWishlist(image?.mediaUpload?.id)} className="cursor-pointer flex flex-row gap-2 hover:text-red-800">
<button className="w-full flex items-center gap-2"> <Icon icon="material-symbols:bookmark-outline" fontSize={25} />
<Icon icon="oi:share" fontSize={20} /> <p className="text-base font-semibold mb-2">{t("save")}</p>
<p className="text-base font-semibold mb-3">Bagikan</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">Share Ke Email</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">Email Tujuan :</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder="Tekan Enter untuk input Email" />
</div> </div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}> <Link href={`/content-management/rewrite/create/${image?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
Kirim <Icon icon="jam:write" fontSize={25} />
</Button> <p className="text-base font-semibold mb-2">Content Rewrite</p>
</div> </Link>
</PopoverContent> <div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
</Popover> <Popover>
<PopoverTrigger asChild>
<button className="w-full flex flex-row items-center gap-3">
<Icon icon="oi:share" fontSize={20} />
<p className="text-base font-semibold mb-1"> {t("share")}</p>
</button>
</PopoverTrigger>
<PopoverContent>
<div className="flex flex-col">
<h1 className="mb-2">{t("shareTo")}</h1>
<div className="flex flex-col mb-2">
<p className="text-base font-semibold mb-1">{t("destinationEmail")}</p>
<Input value={emailShareInput} onChange={(event) => setEmailShareInput(event.target.value)} onKeyPress={handleEmailList} type="email" placeholder={t("pressEnter")} />
</div>
<Button className="bg-blue-500 text-white p-2 w-fit rounded-lg" onClick={() => shareToEmail()}>
{t("send")}
</Button>
</div>
</PopoverContent>
</Popover>
</div>
</PopoverContent>
</Popover>
</p>
</div> </div>
<a onClick={() => handleDelete(image?.id)} className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg"> </div>
<Icon icon="fa:trash" fontSize={20} /> </div>
<p className="text-base font-semibold">Hapus</p>
</a>
</PopoverContent>
</Popover>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -2,7 +2,7 @@
import HeaderManagement from "@/components/landing-page/header-management"; import HeaderManagement from "@/components/landing-page/header-management";
import SidebarManagement from "@/components/landing-page/sidebar-management"; import SidebarManagement from "@/components/landing-page/sidebar-management";
import { close, error, loading } from "@/config/swal"; import { close, loading } from "@/config/swal";
import { getCookiesDecrypt } from "@/lib/utils"; import { getCookiesDecrypt } from "@/lib/utils";
import { getInfoProfile, getUsersTeams, saveUserReports } from "@/service/landing/landing"; import { getInfoProfile, getUsersTeams, saveUserReports } from "@/service/landing/landing";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
@ -10,9 +10,9 @@ import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, Di
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import toast from "react-hot-toast";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { ToastAction } from "@/components/ui/toast"; import Image from "next/image";
import { useTranslations } from "next-intl";
const page = () => { const page = () => {
const [user, setUser] = useState<any>(); const [user, setUser] = useState<any>();
@ -23,6 +23,7 @@ const page = () => {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const { toast } = useToast(); const { toast } = useToast();
const [reportMessageOpen, setReportMessageOpen] = useState(false); const [reportMessageOpen, setReportMessageOpen] = useState(false);
const t = useTranslations("LandingPage");
// const launchModal = (user: any) => { // const launchModal = (user: any) => {
// setUserSelected(user); // setUserSelected(user);
@ -118,25 +119,22 @@ const page = () => {
<SidebarManagement /> <SidebarManagement />
<div className="w-2/3 p-12"> <div className="w-2/3 p-12">
<div className="flex flex-col"> <div className="flex flex-col">
<p className="text-lg font-semibold">Tim {profile?.institute?.name}</p> <p className="text-2xl w-fit font-bold bg-[#bb3523] px-4 py-1 rounded-lg text-center text-white my-4 ">
<p className="text-base mb-3">{user?.length} Anggota</p> <span className="text-black">{t("team")} </span>
{profile?.institute?.name}
</p>
<p className="text-base mb-3">
{user?.length} {t("teamMembers")} {profile?.institute?.name}
</p>
</div> </div>
<div className="flex flex-row gap-5"> <div className="flex flex-row gap-5">
{user?.map((row: any) => ( {user?.map((row: any) => (
<div key={row?.id}> <div key={row?.id}>
<Dialog> <Dialog>
<DialogTrigger> <DialogTrigger>
<div className="flex flex-col items-center"> <div className="flex flex-col items-center border border-gray-500 p-2 bg-[#f8f8f8] rounded-md">
<svg xmlns="http://www.w3.org/2000/svg" width="5em" height="5em" viewBox="0 0 16 16"> <Image src="/assets/gg-profile.png" alt="" width={1280} height={720} className="h-10 w-10 mb-4" />
<path fill="currentColor" d="M11 7c0 1.66-1.34 3-3 3S5 8.66 5 7s1.34-3 3-3s3 1.34 3 3" /> <p className="font-bold text-base ">{row?.fullname}</p>
<path
fill="black"
fill-rule="evenodd"
d="M16 8c0 4.42-3.58 8-8 8s-8-3.58-8-8s3.58-8 8-8s8 3.58 8 8M4 13.75C4.16 13.484 5.71 11 7.99 11c2.27 0 3.83 2.49 3.99 2.75A6.98 6.98 0 0 0 14.99 8c0-3.87-3.13-7-7-7s-7 3.13-7 7c0 2.38 1.19 4.49 3.01 5.75"
clip-rule="evenodd"
/>
</svg>
<p className="font-semibold text-md">{row?.fullname}</p>
<p className="text-sm font-light">{row?.username || "username"}</p> <p className="text-sm font-light">{row?.username || "username"}</p>
</div> </div>
</DialogTrigger> </DialogTrigger>
@ -166,7 +164,7 @@ const page = () => {
</div> </div>
<div className="border-b border-black w-full"></div> <div className="border-b border-black w-full"></div>
<div className="flex flex-col"> <div className="flex flex-col">
<h1 className="text-red-600 mb-2">Alasan Report Akun</h1> <h1 className="text-red-600 mb-2">{t("reasonReport")}</h1>
<textarea id="formControlTextarea1" rows={4} className="border border-black font-light" onChange={(e: any) => setReportMessage(e.target.value)} /> <textarea id="formControlTextarea1" rows={4} className="border border-black font-light" onChange={(e: any) => setReportMessage(e.target.value)} />
</div> </div>
</div> </div>
@ -174,17 +172,17 @@ const page = () => {
<Dialog> <Dialog>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button className="bg-red-500 text-white" type="submit"> <Button className="bg-red-500 text-white" type="submit">
Kirim {t("send")}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>
<h1>Simpan Data?</h1> <h1>{t("saveData")}</h1>
<DialogFooter> <DialogFooter>
<DialogClose> <DialogClose>
<Button onClick={save}>Simpan</Button> <Button onClick={save}>{t("save")}</Button>
</DialogClose> </DialogClose>
<DialogClose> <DialogClose>
<Button>Cancel</Button> <Button>{t("cancel")}</Button>
</DialogClose> </DialogClose>
</DialogFooter> </DialogFooter>
</DialogContent> </DialogContent>

View File

@ -14,7 +14,7 @@ import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals"; import { checkMaliciousText, formatDateToIndonesian, getPublicLocaleTimestamp } from "@/utils/globals";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import parse from "html-react-parser"; import parse from "html-react-parser";
@ -435,12 +435,16 @@ const DetailDocument = () => {
<p className="text-xs lg:text-sm"> <p className="text-xs lg:text-sm">
{t("by")}&nbsp;<span className="font-semibold text-black">{detailDataDocument?.uploadedBy?.userLevel?.name}</span> {t("by")}&nbsp;<span className="font-semibold text-black">{detailDataDocument?.uploadedBy?.userLevel?.name}</span>
</p> </p>
<p className="text-xs lg:text-sm"> {/* <p className="text-xs lg:text-sm">
&nbsp;|&nbsp; {t("updatedOn")} {detailDataDocument?.updatedAt} WIB &nbsp;|&nbsp; &nbsp;|&nbsp; {t("updatedOn")} {detailDataDocument?.updatedAt} WIB &nbsp;|&nbsp;
</p> */}
<p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")}&nbsp;
{formatDateToIndonesian(new Date(detailDataDocument?.updatedAt))} {"WIB"}
</p> </p>
<p className="text-xs lg:text-sm flex justify-center items-center"> <p className="text-xs lg:text-sm flex justify-center items-center">
<Icon icon="formkit:eye" width="15" height="15" /> &nbsp;| &nbsp;<Icon icon="formkit:eye" width="15" height="15" />
&nbsp; {detailDataDocument?.clickCount} &nbsp; &nbsp;{detailDataDocument?.clickCount}&nbsp;
</p> </p>
</div> </div>
<div className="mt-3"> <div className="mt-3">
@ -453,7 +457,7 @@ const DetailDocument = () => {
{/* Keterangan */} {/* Keterangan */}
<div className=""> <div className="">
<h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8 text-justify">{detailDataDocument?.title}</h1> <h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8 text-justify space-y-4">{detailDataDocument?.title}</h1>
<div dangerouslySetInnerHTML={{ __html: detailDataDocument?.htmlDescription }} /> <div dangerouslySetInnerHTML={{ __html: detailDataDocument?.htmlDescription }} />
</div> </div>
</div> </div>

View File

@ -1,6 +1,7 @@
"use client"; "use client";
import { Reveal } from "@/components/landing-page/Reveal"; import { Reveal } from "@/components/landing-page/Reveal";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslations } from "next-intl";
interface FAQItem { interface FAQItem {
question: string; question: string;
@ -8,22 +9,24 @@ interface FAQItem {
} }
const FAQS: React.FC = () => { const FAQS: React.FC = () => {
const t = useTranslations("LandingPage");
const faqs: FAQItem[] = [ const faqs: FAQItem[] = [
{ {
question: "APA SAJA KONTEN-KONTEN YANG ADA DI MEDIAHUB DAN KATEGORI DI DALAMNYA?", question: t("question1"),
answer: "MediaHub memiliki beragam konten seperti berita, video, dan dokumen yang dikategorikan dalam topik seperti edukasi, hiburan, dan informasi terkini.", answer: t("answer1"),
}, },
{ {
question: "BAGAIMANA KONTEN DARI MEDIAHUB DAPAT DIUNDUH?", question: t("question2"),
answer: "Anda dapat mengunduh konten dengan klik tombol unduh yang tersedia pada setiap konten di halaman MediaHub.", answer: t("answer2"),
}, },
{ {
question: "SIAPA SAJA YANG DAPAT MENDAFTARKAN DIRI SEBAGAI PENGGUNA MEDIAHUB?", question: t("question3"),
answer: "Semua orang yang memiliki minat terhadap konten di MediaHub dapat mendaftar sebagai pengguna, baik untuk personal maupun profesional.", answer: t("answer3"),
}, },
{ {
question: "APA ITU MEDIAHUB? DAN APA SAJA FITUR YANG ADA DI DALAMNYA?", question: t("question4"),
answer: "MediaHub adalah platform yang menyediakan berbagai konten informatif dan edukatif. Fitur utama meliputi pencarian, pengunduhan, dan personalisasi konten.", answer: t("answer4"),
}, },
]; ];
@ -44,7 +47,7 @@ const FAQS: React.FC = () => {
{/* FAQS Items */} {/* FAQS Items */}
<div className="space-y-4"> <div className="space-y-4">
{faqs.map((faq, index) => ( {faqs?.map((faq, index) => (
<div key={index} className="border-b border-gray-300 pb-2 cursor-pointer"> <div key={index} className="border-b border-gray-300 pb-2 cursor-pointer">
<div className="flex justify-between items-center" onClick={() => toggleFAQ(index)}> <div className="flex justify-between items-center" onClick={() => toggleFAQ(index)}>
<h3 className="text-sm font-semibold text-gray-800">{faq.question}</h3> <h3 className="text-sm font-semibold text-gray-800">{faq.question}</h3>

View File

@ -4,7 +4,7 @@ import { Reveal } from "@/components/landing-page/Reveal";
import { error, loading, successCallback } from "@/config/swal"; import { error, loading, successCallback } from "@/config/swal";
import { getFeedback, postUserFeedback } from "@/service/landing/landing"; import { getFeedback, postUserFeedback } from "@/service/landing/landing";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { any } from "zod"; import { useTranslations } from "next-intl";
interface RatingProps { interface RatingProps {
label: string; label: string;
@ -57,6 +57,7 @@ const FeedbackForm: React.FC = () => {
const [userFeedbacks, setUserFeedbacks] = useState<Feedback[]>([]); const [userFeedbacks, setUserFeedbacks] = useState<Feedback[]>([]);
const [hasMounted, setHasMounted] = useState(false); const [hasMounted, setHasMounted] = useState(false);
const t = useTranslations("LandingPage");
const handleRatingChange = (id: any, score: any) => { const handleRatingChange = (id: any, score: any) => {
const listData = [...userFeedbacks]; const listData = [...userFeedbacks];
@ -119,14 +120,14 @@ const FeedbackForm: React.FC = () => {
<div className="max-w-6xl flex flex-col mx-auto p-4 lg:p-40 gap-5"> <div className="max-w-6xl flex flex-col mx-auto p-4 lg:p-40 gap-5">
<div className="flex items-center justify-center mb-6"> <div className="flex items-center justify-center mb-6">
<img src="/assets/icons-feedback.png" alt="Feedback" /> <img src="/assets/icons-feedback.png" alt="Feedback" />
<h2 className="ml-4 text-[15px] lg:text-[32px] font-bold text-gray-800">Feedback Pengguna</h2> <h2 className="ml-4 text-[15px] lg:text-[32px] font-bold text-gray-800">{t("userFeedback")}</h2>
</div> </div>
<Rating label="Silakan berikan rating Anda terkait dengan kemudahan akses website MediaHUB Polri" onRate={(rating) => handleRatingChange("accessibility", rating)} /> <Rating label={t("ratings")} onRate={(rating) => handleRatingChange("accessibility", rating)} />
<Rating label="Silakan berikan rating Anda terkait dengan tampilan website MediaHUB Polri" onRate={(rating) => handleRatingChange("appearance", rating)} /> <Rating label={t("ratings2")} onRate={(rating) => handleRatingChange("appearance", rating)} />
<Rating label="Silakan berikan rating Anda terkait dengan konten MediaHUB Polri" onRate={(rating) => handleRatingChange("content", rating)} /> <Rating label={t("ratings3")} onRate={(rating) => handleRatingChange("content", rating)} />
<div className="flex justify-center"> <div className="flex justify-center">
<button onClick={handleSubmit} className="w-fit lg:w-32 bg-[#2F80ED] text-white py-2 px-4 gap-4 rounded-md hover:bg-blue-600 transition text-sm lg:text-base"> <button onClick={handleSubmit} className="w-fit lg:w-32 bg-[#2F80ED] text-white py-2 px-4 gap-4 rounded-md hover:bg-blue-600 transition text-sm lg:text-base">
Kirim {t("send")}
</button> </button>
</div> </div>
</div> </div>

View File

@ -14,7 +14,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"; import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking";
import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals"; import { checkMaliciousText, formatDateToIndonesian, getPublicLocaleTimestamp } from "@/utils/globals";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import parse from "html-react-parser"; import parse from "html-react-parser";
@ -473,11 +473,16 @@ const DetailInfo = () => {
<p className="text-xs lg:text-sm"> <p className="text-xs lg:text-sm">
{t("by")}&nbsp;<span className="font-semibold text-black">{detailDataImage?.uploadedBy?.userLevel?.name}</span> {t("by")}&nbsp;<span className="font-semibold text-black">{detailDataImage?.uploadedBy?.userLevel?.name}</span>
</p> </p>
<p className="text-xs lg:text-sm"> {/* <p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")} &nbsp;|&nbsp;{t("updatedOn")}
{detailDataImage?.updatedAt} WIB &nbsp;|&nbsp; {detailDataImage?.updatedAt} WIB &nbsp;|&nbsp;
</p> */}
<p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")}&nbsp;
{formatDateToIndonesian(new Date(detailDataImage?.updatedAt))} {"WIB"}
</p> </p>
<p className="text-xs lg:text-sm flex justify-center items-center"> <p className="text-xs lg:text-sm flex justify-center items-center">
&nbsp;|&nbsp;
<Icon icon="formkit:eye" width="15" height="15" /> <Icon icon="formkit:eye" width="15" height="15" />
&nbsp; {detailDataImage?.clickCount} &nbsp; &nbsp; {detailDataImage?.clickCount} &nbsp;
</p> </p>
@ -493,7 +498,7 @@ const DetailInfo = () => {
{/* Keterangan */} {/* Keterangan */}
<div className="w-full"> <div className="w-full">
<h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8">{detailDataImage?.title}</h1> <h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8">{detailDataImage?.title}</h1>
<div className="font-light text-justify mb-5 lg:mb-0" dangerouslySetInnerHTML={{ __html: detailDataImage?.htmlDescription }} /> <div className="font-light text-justify mb-5 space-y-4 lg:mb-0" dangerouslySetInnerHTML={{ __html: detailDataImage?.htmlDescription }} />
</div> </div>
</div> </div>

View File

@ -7,12 +7,14 @@ import { Icon } from "@iconify/react/dist/iconify.js";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslations } from "next-intl";
const InboxSection = () => { const InboxSection = () => {
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const isUpdate = pathname.includes("update"); const isUpdate = pathname.includes("update");
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const t = useTranslations("LandingPage");
const page: any = searchParams?.get("page"); const page: any = searchParams?.get("page");
@ -53,20 +55,20 @@ const InboxSection = () => {
<path d="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11s11-4.925 11-11S18.075 1 12 1M3 12c0 2.09.713 4.014 1.908 5.542A8.99 8.99 0 0 1 12.065 14a8.98 8.98 0 0 1 7.092 3.458A9 9 0 1 0 3 12m9 9a8.96 8.96 0 0 1-5.672-2.012A6.99 6.99 0 0 1 12.065 16a6.99 6.99 0 0 1 5.689 2.92A8.96 8.96 0 0 1 12 21" /> <path d="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11s11-4.925 11-11S18.075 1 12 1M3 12c0 2.09.713 4.014 1.908 5.542A8.99 8.99 0 0 1 12.065 14a8.98 8.98 0 0 1 7.092 3.458A9 9 0 1 0 3 12m9 9a8.96 8.96 0 0 1-5.672-2.012A6.99 6.99 0 0 1 12.065 16a6.99 6.99 0 0 1 5.689 2.92A8.96 8.96 0 0 1 12 21" />
</g> </g>
</svg>{" "} </svg>{" "}
<h2 className="ml-4 text-[15px] lg:text-[32px] font-semibold text-gray-800">Pesan Masuk</h2> <h2 className="ml-4 text-[15px] lg:text-[32px] font-semibold text-gray-800">{t("inbox")}</h2>
</div> </div>
<div className="flex flex-col justify-center items-center gap-3"> <div className="flex flex-col justify-center items-center gap-3">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="flex flex-row gap-10 items-center justify-center"> <div className="flex flex-row gap-10 items-center justify-center">
<div className=""> <div className="">
<p className="bg-[#bb3523] py-1 px-3 rounded-full">Pesan Masuk</p> <p className="bg-[#bb3523] py-1 px-3 rounded-full">{t("inbox")}</p>
</div> </div>
<Link href={`/inbox/update`}>Update</Link> <Link href={`/inbox/update`}>{t("update")}</Link>
</div> </div>
</div> </div>
<div className="py-10 px-8 w-[400px] mt-3 border border-black rounded-lg flex flex-col"> <div className="py-10 px-8 w-[400px] mt-3 border border-black rounded-lg flex flex-col">
<h1 className="mb-3 text-lg font-semibold">List Notifikasi</h1> <h1 className="mb-3 text-lg font-semibold">{t("notifList")}</h1>
<div className="hover:bg-slate-200 rounded-md"> <div className="hover:bg-slate-200 rounded-md">
{notifications?.map((list: any) => ( {notifications?.map((list: any) => (
<a className="flex flex-row items-center ml-1" href={"/" + list.redirectUrl}> <a className="flex flex-row items-center ml-1" href={"/" + list.redirectUrl}>

View File

@ -5,8 +5,8 @@ import { getUserNotifications } from "@/service/landing/landing";
import { getTimestamp } from "@/utils/globals"; import { getTimestamp } from "@/utils/globals";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslations } from "next-intl";
const UpdateSection = () => { const UpdateSection = () => {
const pathname = usePathname(); const pathname = usePathname();
@ -14,7 +14,7 @@ const UpdateSection = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const page: any = searchParams?.get("page"); const page: any = searchParams?.get("page");
const pages = page ? page - 1 : 0; const pages = page ? page - 1 : 0;
const t = useTranslations("LandingPage");
const [notifications, setNotifications] = useState([]); const [notifications, setNotifications] = useState([]);
const [getTotalData, setGetTotalData] = useState(); const [getTotalData, setGetTotalData] = useState();
const [, setGetTotalPage] = useState(); const [, setGetTotalPage] = useState();
@ -50,20 +50,20 @@ const UpdateSection = () => {
<path d="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11s11-4.925 11-11S18.075 1 12 1M3 12c0 2.09.713 4.014 1.908 5.542A8.99 8.99 0 0 1 12.065 14a8.98 8.98 0 0 1 7.092 3.458A9 9 0 1 0 3 12m9 9a8.96 8.96 0 0 1-5.672-2.012A6.99 6.99 0 0 1 12.065 16a6.99 6.99 0 0 1 5.689 2.92A8.96 8.96 0 0 1 12 21" /> <path d="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11s11-4.925 11-11S18.075 1 12 1M3 12c0 2.09.713 4.014 1.908 5.542A8.99 8.99 0 0 1 12.065 14a8.98 8.98 0 0 1 7.092 3.458A9 9 0 1 0 3 12m9 9a8.96 8.96 0 0 1-5.672-2.012A6.99 6.99 0 0 1 12.065 16a6.99 6.99 0 0 1 5.689 2.92A8.96 8.96 0 0 1 12 21" />
</g> </g>
</svg>{" "} </svg>{" "}
<h2 className="ml-4 text-[15px] lg:text-[32px] font-semibold text-gray-800">Update</h2> <h2 className="ml-4 text-[15px] lg:text-[32px] font-semibold text-gray-800">{t("update")}</h2>
</div> </div>
<div className="flex flex-col items-center gap-3"> <div className="flex flex-col items-center gap-3">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="flex flex-row gap-10 items-center justify-center"> <div className="flex flex-row gap-10 items-center justify-center">
<div> <div>
<Link href={`/inbox`}>Pesan Masuk</Link> <Link href={`/inbox`}>{t("inbox")}</Link>
</div> </div>
<div className="bg-[#bb3523] py-1 px-3 rounded-full">Update</div> <div className="bg-[#bb3523] py-1 px-3 rounded-full">{t("update")}</div>
</div> </div>
</div> </div>
<div className="py-10 px-8 w-[400px] mt-3 border border-black rounded-lg flex flex-col"> <div className="py-10 px-8 w-[400px] mt-3 border border-black rounded-lg flex flex-col">
<h1 className="mb-3 text-lg font-semibold">List Notifikasi</h1> <h1 className="mb-3 text-lg font-semibold">{t("notifList")}</h1>
<div className="hover:bg-slate-200 rounded-md"> <div className="hover:bg-slate-200 rounded-md">
{notifications?.map((list: any) => ( {notifications?.map((list: any) => (
<a className="flex flex-row items-center ml-1" href={"/" + list.redirectUrl}> <a className="flex flex-row items-center ml-1" href={"/" + list.redirectUrl}>

View File

@ -16,6 +16,7 @@ import withReactContent from "sweetalert2-react-content";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const profileSchema = z.object({ const profileSchema = z.object({
password: z.string().min(1, { message: "Judul diperlukan" }), password: z.string().min(1, { message: "Judul diperlukan" }),
@ -33,6 +34,7 @@ const ChangePassword: React.FC = () => {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const [detail, setDetail] = useState<Detail>(); const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const t = useTranslations("LandingPage");
type ProfileSchema = z.infer<typeof profileSchema>; type ProfileSchema = z.infer<typeof profileSchema>;
const { const {
@ -100,86 +102,45 @@ const ChangePassword: React.FC = () => {
<div className="w-20 h-20 mx-auto rounded-full bg-red-700 flex items-center justify-center"> <div className="w-20 h-20 mx-auto rounded-full bg-red-700 flex items-center justify-center">
<span className="text-white text-3xl font-bold">👤</span> <span className="text-white text-3xl font-bold">👤</span>
</div> </div>
<h1 className="text-2xl font-bold mt-4">Ubah Profile</h1> <h1 className="text-2xl font-bold mt-4">{t("changePass")}</h1>
</div> </div>
<div className="flex justify-center gap-4 mb-8"> <div className="flex justify-center gap-4 mb-8">
<Link href={"/profile"}> <Link href={"/profile"}>
<button className="border border-red-700 text-red-700 px-4 py-2 rounded"> <button className="border border-red-700 text-red-700 px-4 py-2 rounded">{t("userProfile")}</button>
User Profile
</button>
</Link> </Link>
<Link href={"/profile/change-profile"}> <Link href={"/profile/change-profile"}>
<button className="border border-red-700 text-red-700 px-4 py-2 rounded"> <button className="border border-red-700 text-red-700 px-4 py-2 rounded">{t("changePhoto")}</button>
Ubah Foto
</button>
</Link> </Link>
<Link href={"/profile/change-password"}> <Link href={"/profile/change-password"}>
<button className="bg-red-700 text-white px-4 py-2 rounded"> <button className="bg-red-700 text-white px-4 py-2 rounded">{t("changePass")}</button>
Ubah Password
</button>
</Link> </Link>
</div> </div>
<div className="max-w-3xl mx-auto bg-white shadow-sm p-4 rounded"> <div className="max-w-3xl mx-auto bg-white shadow-sm p-4 rounded">
<p className="mb-6 text-gray-600"> <p className="mb-6 text-gray-600">{t("pleaseChange")}</p>
Silahkan ubah data pribadi Anda pada form berikut.
</p>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div> <div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Password<span className="text-red-500">*</span> {t("password")}
<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="password" render={({ field }) => <Input size="md" type="password" defaultValue={field.value} onChange={field.onChange} placeholder={t("inputPass")} />} />
control={control} {errors.password?.message && <p className="text-red-400 text-sm">{errors.password.message}</p>}
name="password"
render={({ field }) => (
<Input
size="md"
type="password"
defaultValue={field.value}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.password?.message && (
<p className="text-red-400 text-sm">
{errors.password.message}
</p>
)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Konfirmasi Password<span className="text-red-500">*</span> {t("confirmPass")}
<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="retypePassword" render={({ field }) => <Input size="md" type="password" defaultValue={field.value} onChange={field.onChange} placeholder={t("samePass")} />} />
control={control} {errors.retypePassword?.message && <p className="text-red-400 text-sm">{errors.retypePassword.message}</p>}
name="retypePassword"
render={({ field }) => (
<Input
size="md"
type="password"
defaultValue={field.value}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.retypePassword?.message && (
<p className="text-red-400 text-sm">
{errors.retypePassword.message}
</p>
)}
</div> </div>
<div className="text-right"> <div className="text-right">
<div className="mt-4"> <div className="mt-4">
<button <button type="submit" className="bg-red-700 text-white px-6 py-2 rounded hover:bg-red-800 focus:outline-none focus:ring focus:ring-red-300">
type="submit" {t("save")}
className="bg-red-700 text-white px-6 py-2 rounded hover:bg-red-800 focus:outline-none focus:ring focus:ring-red-300"
>
Simpan
</button> </button>
</div> </div>
</div> </div>

View File

@ -2,9 +2,11 @@
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import Image from "next/image"; import Image from "next/image";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslations } from "next-intl";
const ChangeProfile: React.FC = () => { const ChangeProfile: React.FC = () => {
const [selectedImage, setSelectedImage] = useState<File | null>(null); const [selectedImage, setSelectedImage] = useState<File | null>(null);
const t = useTranslations("LandingPage");
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files[0]) { if (e.target.files && e.target.files[0]) {
@ -32,35 +34,35 @@ const ChangeProfile: React.FC = () => {
<div className="w-20 h-20 mx-auto rounded-full bg-red-700 flex items-center justify-center"> <div className="w-20 h-20 mx-auto rounded-full bg-red-700 flex items-center justify-center">
<span className="text-white text-3xl font-bold">👤</span> <span className="text-white text-3xl font-bold">👤</span>
</div> </div>
<h1 className="text-2xl font-bold mt-4">Ubah Photo</h1> <h1 className="text-2xl font-bold mt-4">{t("changePhoto")}</h1>
</div> </div>
<div className="flex justify-center gap-4 mb-8"> <div className="flex justify-center gap-4 mb-8">
<Link href={"/profile"}> <Link href={"/profile"}>
<button className="border border-red-700 text-red-700 px-4 py-2 rounded">User Profile</button> <button className="border border-red-700 text-red-700 px-4 py-2 rounded">{t("userProfile")}</button>
</Link> </Link>
<Link href={"/profile/change-profile"}> <Link href={"/profile/change-profile"}>
<button className="bg-red-700 text-white px-4 py-2 rounded">Ubah Foto</button> <button className="bg-red-700 text-white px-4 py-2 rounded">{t("changePhoto")}</button>
</Link> </Link>
<Link href={"/profile/change-password"}> <Link href={"/profile/change-password"}>
<button className="border border-red-700 text-red-700 px-4 py-2 rounded">Ubah Password</button> <button className="border border-red-700 text-red-700 px-4 py-2 rounded">{t("changePass")}</button>
</Link> </Link>
</div> </div>
<div className="w-80 mx-auto bg-gray-900 text-white shadow-md p-8 rounded"> <div className="w-80 mx-auto bg-gray-900 text-white shadow-md p-8 rounded">
<div className="flex justify-center mb-6"> <div className="flex justify-center mb-6">
<div className="w-40 h-40 rounded-full border border-gray-300 flex items-center justify-center"> <div className="w-40 h-40 rounded-full border border-gray-300 flex items-center justify-center">
{selectedImage ? <Image width={1920} height={1080} src={URL.createObjectURL(selectedImage)} alt="Preview" className="w-full h-full rounded-full object-cover" /> : <span className="text-gray-500">No Image</span>} {selectedImage ? <Image width={1920} height={1080} src={URL.createObjectURL(selectedImage)} alt="Preview" className="w-full h-full rounded-full object-cover" /> : <span className="text-gray-500">{t("noImage")}</span>}
</div> </div>
</div> </div>
<div className="flex justify-center gap-4"> <div className="flex justify-center gap-4">
<input type="file" id="upload" accept="image/*" className="hidden" onChange={handleImageChange} /> <input type="file" id="upload" accept="image/*" className="hidden" onChange={handleImageChange} />
<label htmlFor="upload" className="bg-blue-600 text-white px-4 py-2 rounded cursor-pointer"> <label htmlFor="upload" className="bg-blue-600 text-white px-4 py-2 rounded cursor-pointer">
Ganti Foto {t("changePhoto")}
</label> </label>
<button onClick={handleDelete} className="border border-red-700 text-red-700 px-4 py-2 rounded"> <button onClick={handleDelete} className="border border-red-700 text-red-700 px-4 py-2 rounded">
Hapus Foto {t("deletePhoto")}{" "}
</button> </button>
</div> </div>
</div> </div>

View File

@ -16,15 +16,14 @@ import withReactContent from "sweetalert2-react-content";
import { Textarea } from "@/components/ui/textarea"; import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Link } from "@/components/navigation"; import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl";
const profileSchema = z.object({ const profileSchema = z.object({
username: z.string().min(1, { message: "Judul diperlukan" }), username: z.string().min(1, { message: "Judul diperlukan" }),
fullname: z.string().min(1, { message: "Judul diperlukan" }), fullname: z.string().min(1, { message: "Judul diperlukan" }),
memberIdentity: z.string().min(1, { message: "Judul diperlukan" }), memberIdentity: z.string().min(1, { message: "Judul diperlukan" }),
email: z.string().min(1, { message: "Judul diperlukan" }), email: z.string().min(1, { message: "Judul diperlukan" }),
address: z address: z.string().min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
.string()
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
phoneNumber: z.string().min(1, { message: "Kategori diperlukan" }), phoneNumber: z.string().min(1, { message: "Kategori diperlukan" }),
}); });
@ -45,6 +44,7 @@ const UbahProfile: React.FC = () => {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const [detail, setDetail] = useState<Detail>(); const [detail, setDetail] = useState<Detail>();
const [refresh, setRefresh] = useState(false); const [refresh, setRefresh] = useState(false);
const t = useTranslations("LandingPage");
type ProfileSchema = z.infer<typeof profileSchema>; type ProfileSchema = z.infer<typeof profileSchema>;
const { const {
@ -117,30 +117,22 @@ const UbahProfile: React.FC = () => {
<div className="w-20 h-20 mx-auto rounded-full bg-red-700 flex items-center justify-center"> <div className="w-20 h-20 mx-auto rounded-full bg-red-700 flex items-center justify-center">
<span className="text-white text-3xl font-bold">👤</span> <span className="text-white text-3xl font-bold">👤</span>
</div> </div>
<h1 className="text-2xl font-bold mt-4">Ubah Profile</h1> <h1 className="text-2xl font-bold mt-4">{t("changeProfile")}</h1>
</div> </div>
<div className="flex justify-center gap-4 mb-8"> <div className="flex justify-center gap-4 mb-8">
<Link href={"/profile"}> <Link href={"/profile"}>
<button className="bg-red-700 text-white px-4 py-2 rounded"> <button className="bg-red-700 text-white px-4 py-2 rounded">{t("userProfile")}</button>
User Profile
</button>
</Link> </Link>
<Link href={"/profile/change-profile"}> <Link href={"/profile/change-profile"}>
<button className="border border-red-700 text-red-700 px-4 py-2 rounded"> <button className="border border-red-700 text-red-700 px-4 py-2 rounded">{t("changePhoto")}</button>
Ubah Foto
</button>
</Link> </Link>
<Link href={"/profile/change-password"}> <Link href={"/profile/change-password"}>
<button className="border border-red-700 text-red-700 px-4 py-2 rounded"> <button className="border border-red-700 text-red-700 px-4 py-2 rounded">{t("changePass")}</button>
Ubah Password
</button>
</Link> </Link>
</div> </div>
<div className="max-w-3xl mx-auto bg-white shadow-sm p-4 rounded"> <div className="max-w-3xl mx-auto bg-white shadow-sm p-4 rounded">
<p className="mb-6 text-gray-600"> <p className="mb-6 text-gray-600">{t("pleaseChange")}</p>
Silahkan ubah data pribadi Anda pada form berikut.
</p>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
{detail !== undefined ? ( {detail !== undefined ? (
<div> <div>
@ -148,143 +140,52 @@ const UbahProfile: React.FC = () => {
<Label> <Label>
Username<span className="text-red-500">*</span> Username<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="username" render={({ field }) => <Input size="md" type="text" defaultValue={detail?.username} onChange={field.onChange} placeholder="Enter Title" />} />
control={control} {errors.username?.message && <p className="text-red-400 text-sm">{errors.username.message}</p>}
name="username"
render={({ field }) => (
<Input
size="md"
type="text"
defaultValue={detail?.username}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.username?.message && (
<p className="text-red-400 text-sm">
{errors.username.message}
</p>
)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Nama Lengkap<span className="text-red-500">*</span> {t("fullName")}
<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="fullname" render={({ field }) => <Input size="md" type="text" defaultValue={detail?.fullname} onChange={field.onChange} placeholder="Enter Title" />} />
control={control} {errors.fullname?.message && <p className="text-red-400 text-sm">{errors.fullname.message}</p>}
name="fullname"
render={({ field }) => (
<Input
size="md"
type="text"
defaultValue={detail?.fullname}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.fullname?.message && (
<p className="text-red-400 text-sm">
{errors.fullname.message}
</p>
)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Nomor Identitas<span className="text-red-500">*</span> {t("identityNumber")}
<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="memberIdentity" render={({ field }) => <Input size="md" type="text" defaultValue={detail?.memberIdentity} onChange={field.onChange} placeholder="Enter Title" />} />
control={control} {errors.memberIdentity?.message && <p className="text-red-400 text-sm">{errors.memberIdentity.message}</p>}
name="memberIdentity"
render={({ field }) => (
<Input
size="md"
type="text"
defaultValue={detail?.memberIdentity}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.memberIdentity?.message && (
<p className="text-red-400 text-sm">
{errors.memberIdentity.message}
</p>
)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Email<span className="text-red-500">*</span> Email<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="email" render={({ field }) => <Input size="md" type="text" defaultValue={detail?.email} onChange={field.onChange} placeholder="Enter Title" />} />
control={control} {errors.email?.message && <p className="text-red-400 text-sm">{errors.email.message}</p>}
name="email"
render={({ field }) => (
<Input
size="md"
type="text"
defaultValue={detail?.email}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.email?.message && (
<p className="text-red-400 text-sm">{errors.email.message}</p>
)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Nomor HP<span className="text-red-500">*</span> {t("number")}
<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="phoneNumber" render={({ field }) => <Input size="md" type="number" defaultValue={detail?.phoneNumber} onChange={field.onChange} placeholder="Enter Title" />} />
control={control} {errors.phoneNumber?.message && <p className="text-red-400 text-sm">{errors.phoneNumber.message}</p>}
name="phoneNumber"
render={({ field }) => (
<Input
size="md"
type="number"
defaultValue={detail?.phoneNumber}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.phoneNumber?.message && (
<p className="text-red-400 text-sm">
{errors.phoneNumber.message}
</p>
)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<Label> <Label>
Alamat<span className="text-red-500">*</span> {t("address")}
<span className="text-red-500">*</span>
</Label> </Label>
<Controller <Controller control={control} name="address" render={({ field }) => <Textarea defaultValue={detail?.address} onChange={field.onChange} placeholder="Enter Title" />} />
control={control} {errors.address?.message && <p className="text-red-400 text-sm">{errors.address.message}</p>}
name="address"
render={({ field }) => (
<Textarea
defaultValue={detail?.address}
onChange={field.onChange}
placeholder="Enter Title"
/>
)}
/>
{errors.address?.message && (
<p className="text-red-400 text-sm">
{errors.address.message}
</p>
)}
</div> </div>
<div className="text-right"> <div className="text-right">
<div className="mt-4"> <div className="mt-4">
<button <button type="submit" className="bg-red-700 text-white px-6 py-2 rounded hover:bg-red-800 focus:outline-none focus:ring focus:ring-red-300">
type="submit" {t("save")}
className="bg-red-700 text-white px-6 py-2 rounded hover:bg-red-800 focus:outline-none focus:ring focus:ring-red-300"
>
Simpan
</button> </button>
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@ import { sendMediaUploadToEmail } from "@/service/media-tracking/media-tracking"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { checkMaliciousText, getPublicLocaleTimestamp } from "@/utils/globals"; import { checkMaliciousText, formatDateToIndonesian, getPublicLocaleTimestamp } from "@/utils/globals";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import parse from "html-react-parser"; import parse from "html-react-parser";
@ -440,13 +440,18 @@ const DetailVideo = () => {
<p className="text-xs lg:text-sm"> <p className="text-xs lg:text-sm">
{t("by")}&nbsp;<span className="font-semibold text-black">{detailDataVideo?.uploadedBy?.userLevel?.name}</span> {t("by")}&nbsp;<span className="font-semibold text-black">{detailDataVideo?.uploadedBy?.userLevel?.name}</span>
</p> </p>
<p className="text-xs lg:text-sm"> {/* <p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")} &nbsp;|&nbsp;{t("updatedOn")}
{detailDataVideo?.updatedAt} WIB &nbsp;|&nbsp; {detailDataVideo?.updatedAt} WIB &nbsp;|&nbsp;
</p> */}
<p className="text-xs lg:text-sm">
&nbsp;|&nbsp;{t("updatedOn")}&nbsp;
{formatDateToIndonesian(new Date(detailDataVideo?.updatedAt))} {"WIB"}
</p> </p>
<p className="text-xs lg:text-sm flex justify-center items-center"> <p className="text-xs lg:text-sm flex justify-center items-center">
&nbsp;|&nbsp;
<Icon icon="formkit:eye" width="15" height="15" /> <Icon icon="formkit:eye" width="15" height="15" />
&nbsp; {detailDataVideo?.clickCount} &nbsp; &nbsp;{detailDataVideo?.clickCount} &nbsp;
</p> </p>
</div> </div>
<div className="mt-3"> <div className="mt-3">
@ -461,7 +466,7 @@ const DetailVideo = () => {
<div className="w-full"> <div className="w-full">
<h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8">{detailDataVideo?.title}</h1> <h1 className="flex flex-row font-bold text-lg lg:text-2xl my-8">{detailDataVideo?.title}</h1>
<div <div
className="font-light text-justify mb-5 lg:mb-0" className="font-light text-justify mb-5 space-y-4 lg:mb-0"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: detailDataVideo?.htmlDescription, __html: detailDataVideo?.htmlDescription,
}} }}

View File

@ -34,7 +34,7 @@ const ContentCategory = (props: { group?: string }) => {
const pathname = usePathname(); const pathname = usePathname();
return ( return (
<div className="mx-auto px-4 lg:px-20 py-10 max-w-screen-2xl "> <div className="mx-auto px-4 lg:px-24 py-10 max-w-screen-2xl ">
<Reveal> <Reveal>
<h2 className="text-center text-xl lg:text-2xl font-bold text-[#bb3523] mb-4"> <h2 className="text-center text-xl lg:text-2xl font-bold text-[#bb3523] mb-4">
{pathname?.split("/")[1] == "in" ? ( {pathname?.split("/")[1] == "in" ? (

View File

@ -60,7 +60,7 @@ const Footer = () => {
<img src="/assets/icon-privacy.png" alt="Privacy" /> <img src="/assets/icon-privacy.png" alt="Privacy" />
<p className="font-semibold text-lg">{t("privacy")}</p> <p className="font-semibold text-lg">{t("privacy")}</p>
</div> </div>
<div className="container text-dark">{parse(String(privacy))}</div> <div className="container text-black space-y-2">{parse(String(privacy))}</div>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div> </div>

View File

@ -4,9 +4,10 @@ import { useParams, usePathname, useRouter } from "next/navigation";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import Skeleton, { SkeletonTheme } from "react-loading-skeleton";
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import { getPublicLocaleTimestamp } from "@/utils/globals"; import { formatDateToIndonesian, getPublicLocaleTimestamp, textEllipsis } from "@/utils/globals";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel"; import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
import Image from "next/image";
const HeaderBannerSatker = () => { const HeaderBannerSatker = () => {
const router = useRouter(); const router = useRouter();
@ -26,7 +27,7 @@ const HeaderBannerSatker = () => {
// } // }
async function fetchData() { async function fetchData() {
const res = await listData("1", "", "", 5, 0, "createdAt", "", "", "satker-"+satkerName); const res = await listData("1", "", "", 5, 0, "createdAt", "", "", "satker-" + satkerName);
let data = res?.data?.data?.content; let data = res?.data?.data?.content;
setContent(data); setContent(data);
setCenterPadding(`${Math.trunc(Number(window.innerWidth) / 10 + 40)}px`); setCenterPadding(`${Math.trunc(Number(window.innerWidth) / 10 + 40)}px`);
@ -70,49 +71,130 @@ const HeaderBannerSatker = () => {
}; };
return ( return (
<div> <div>
{/* Header */} {/* Header Left */}
<div className="p-6 lg:px-16 flex flex-col lg:flex-row"> <div className="flex flex-col lg:flex-row items-start justify-center gap-8 px-4 lg:px-20 py-4 mx-auto w-auto mt-6">
{isBannerLoading ? ( {isBannerLoading ? (
<SkeletonTheme highlightColor="#f2f2f2"> <div className="flex flex-col space-y-3 mx-auto w-full lg:w-2/3">
<Skeleton className="w-[100%] h-[480px]" /> <Skeleton className="h-[310px] lg:h-[420px] rounded-xl" />
</SkeletonTheme> <div className="space-y-2">
) : ( <Skeleton className="h-4 w-[250px]" />
<div className="mt-3"> <Skeleton className="h-4 w-[200px]" />
<Carousel className="w-full h-full"> </div>
<CarouselContent>
{content?.map((row: any) => (
<CarouselItem key={row?.id} className="basis-1/2">
<div className="relative h-[310px] lg:h-[420px]">
<img src={row?.thumbnailLink} alt="" className="w-full h-[310px] lg:h-[420px] rounded-lg" />
<div className="absolute bottom-0 left-0 right-0 bg-transparent backdrop-blur-sm text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">{row?.categoryName}</span>
<Link
href={
Number(row.fileType?.id) == 1
? `${asPath.includes("/satker/") == true ? asPath : ""}/image/detail/${row.slug}`
: Number(row.fileType?.id) == 2
? `/video/detail/${row.slug}`
: Number(row.fileType?.id) == 3
? `/document/detail/${row.slug}`
: `/audio/detail/${row.slug}`
}
>
<h3>{row.title}</h3>
</Link>
<p className="text-xs flex flex-row items-center gap-1 mt-1 text-white">
{getPublicLocaleTimestamp(new Date(row?.createdAt))} WIB {" | "}
<Icon icon="formkit:eye" width="15" height="15" /> {row?.clickCount}
</p>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
</div> </div>
) : (
<Carousel className="lg:w-2/3 lg:h-full ">
<CarouselContent>
{content?.map((row: any) => (
<CarouselItem key={row?.id}>
<div className="relative h-[310px] lg:h-[420px]">
<Image src={row?.thumbnailLink} alt="" width={1920} height={1080} className="w-full h-[310px] lg:h-[420px] rounded-lg object-cover" />
<div className="absolute bottom-0 left-0 right-0 bg-transparent backdrop-blur-sm text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">{row?.categoryName}</span>
<Link
href={
Number(row.fileType?.id) == 1
? `${asPath.includes("/satker/") == true ? asPath : ""}/image/detail/${row.slug}`
: Number(row.fileType?.id) == 2
? `/video/detail/${row.slug}`
: Number(row.fileType?.id) == 3
? `/document/detail/${row.slug}`
: `/audio/detail/${row.slug}`
}
>
<h3>{row.title}</h3>
</Link>
<p className="text-xs flex flex-row items-center gap-1 mt-1 text-white">
{getPublicLocaleTimestamp(new Date(row?.createdAt))} WIB {" | "}
<Icon icon="formkit:eye" width="15" height="15" /> {row?.clickCount}
</p>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)} )}
{/* Section Kanan */}
<div>
{isBannerLoading ? (
<>
<div className="flex items-center gap-4 max-w-sm mx-auto mb-3">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="items-center hidden md:block gap-4 max-w-sm mx-auto mb-3 lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="hidden md:block items-center gap-4 max-w-sm mx-auto mb-3 lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="hidden md:block items-center gap-4 max-w-sm mx-auto mb-3 lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="hidden md:block items-center gap-4 max-w-sm mx-auto lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
</>
) : (
<ul className="py-4 lg:py-0 flex flex-row lg:flex-col gap-4 flex-nowrap w-[95vw] lg:w-auto overflow-x-auto">
{content?.map((item: any) => (
<li key={item?.id} className="flex gap-4 flex-row lg:w-full ">
<div className="flex-shrink-0 w-24 rounded-lg">
<Image width={720} height={480} src={item?.thumbnailLink} alt={item?.title} className="w-full h-[73px] object-cover rounded-lg" />
</div>
<div className="w-[280px] lg:w-auto">
<span className="text-white bg-[#bb3523] px-4 py-1 rounded-lg flex text-[8px] font-bold uppercase w-fit">{item?.categoryName}</span>
<Link
href={
Number(item?.fileType?.id) == 1
? `${asPath.includes("/satker/") == true ? asPath : ""}/image/detail/${item?.slug}`
: Number(item?.fileType?.id) == 2
? `/video/detail/${item?.slug}`
: Number(item?.fileType?.id) == 3
? `/document/detail/${item?.slug}`
: `/audio/detail/${item?.slug}`
}
>
<h3 className="text-base font-bold mt-2">{textEllipsis(item?.title, 30)}</h3>
</Link>
<p className="text-[10px] flex flex-row items-center gap-1 text-gray-500 mt-1">
{formatDateToIndonesian(new Date(item?.createdAt))} {item?.timezone ? item?.timezone : "WIB"} |{" "}
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
/>
</svg>{" "}
{item?.clickCount}
</p>
</div>
</li>
))}
</ul>
)}
</div>
</div> </div>
</div> </div>
); );

View File

@ -4,9 +4,10 @@ import { useParams, usePathname, useRouter } from "next/navigation";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import Skeleton, { SkeletonTheme } from "react-loading-skeleton";
import { Link } from "@/i18n/routing"; import { Link } from "@/i18n/routing";
import { getPublicLocaleTimestamp } from "@/utils/globals"; import { formatDateToIndonesian, getPublicLocaleTimestamp, textEllipsis } from "@/utils/globals";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel"; import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
import Image from "next/image";
const HeaderBanner = () => { const HeaderBanner = () => {
const router = useRouter(); const router = useRouter();
@ -14,7 +15,6 @@ const HeaderBanner = () => {
const poldaName: any = params?.polda_name; const poldaName: any = params?.polda_name;
const asPath: any = usePathname(); const asPath: any = usePathname();
const [content, setContent] = useState([]); const [content, setContent] = useState([]);
const [isBannerLoading, setIsBannerLoading] = useState(true); const [isBannerLoading, setIsBannerLoading] = useState(true);
const [centerPadding, setCenterPadding] = useState<any>(); const [centerPadding, setCenterPadding] = useState<any>();
@ -70,49 +70,130 @@ const HeaderBanner = () => {
}; };
return ( return (
<div> <div>
{/* Header */} {/* Header Left */}
<div className="p-6 lg:px-16 flex flex-col lg:flex-row"> <div className="flex flex-col lg:flex-row items-start justify-center gap-8 px-4 lg:px-20 py-4 mx-auto w-auto mt-6">
{isBannerLoading ? ( {isBannerLoading ? (
<SkeletonTheme highlightColor="#f2f2f2"> <div className="flex flex-col space-y-3 mx-auto w-full lg:w-2/3">
<Skeleton className="w-[100%] h-[480px]" /> <Skeleton className="h-[310px] lg:h-[420px] rounded-xl" />
</SkeletonTheme> <div className="space-y-2">
) : ( <Skeleton className="h-4 w-[250px]" />
<div className="mt-3"> <Skeleton className="h-4 w-[200px]" />
<Carousel className="w-full h-full"> </div>
<CarouselContent>
{content?.map((row: any) => (
<CarouselItem key={row?.id} className="basis-1/2">
<div className="relative h-[310px] lg:h-[420px]">
<img src={row?.thumbnailLink} alt="" className="w-full h-[310px] lg:h-[420px] rounded-lg" />
<div className="absolute bottom-0 left-0 right-0 bg-transparent backdrop-blur-sm text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">{row?.categoryName}</span>
<Link
href={
Number(row.fileType?.id) == 1
? `${asPath.includes("/polda/") == true ? asPath : ""}/image/detail/${row.slug}`
: Number(row.fileType?.id) == 2
? `/video/detail/${row.slug}`
: Number(row.fileType?.id) == 3
? `/document/detail/${row.slug}`
: `/audio/detail/${row.slug}`
}
>
<h3>{row.title}</h3>
</Link>
<p className="text-xs flex flex-row items-center gap-1 mt-1 text-white">
{getPublicLocaleTimestamp(new Date(row?.createdAt))} WIB {" | "}
<Icon icon="formkit:eye" width="15" height="15" /> {row?.clickCount}
</p>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
</div> </div>
) : (
<Carousel className="lg:w-2/3 lg:h-full ">
<CarouselContent>
{content?.map((row: any) => (
<CarouselItem key={row?.id}>
<div className="relative h-[310px] lg:h-[420px]">
<Image src={row?.thumbnailLink} alt="" width={1920} height={1080} className="w-full h-[310px] lg:h-full rounded-lg object-cover" />
<div className="absolute bottom-0 left-0 right-0 bg-transparent backdrop-blur-sm text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">{row?.categoryName}</span>
<Link
href={
Number(row.fileType?.id) == 1
? `${asPath.includes("/polda/") == true ? asPath : ""}/image/detail/${row.slug}`
: Number(row.fileType?.id) == 2
? `/video/detail/${row.slug}`
: Number(row.fileType?.id) == 3
? `/document/detail/${row.slug}`
: `/audio/detail/${row.slug}`
}
>
<h3>{row.title}</h3>
</Link>
<p className="text-xs flex flex-row items-center gap-1 mt-1 text-white">
{getPublicLocaleTimestamp(new Date(row?.createdAt))} WIB {" | "}
<Icon icon="formkit:eye" width="15" height="15" /> {row?.clickCount}
</p>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
)} )}
{/* Header Right */}
<div>
{isBannerLoading ? (
<>
<div className="flex items-center gap-4 max-w-sm mx-auto mb-3">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="items-center hidden md:block gap-4 max-w-sm mx-auto mb-3 lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="hidden md:block items-center gap-4 max-w-sm mx-auto mb-3 lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="hidden md:block items-center gap-4 max-w-sm mx-auto mb-3 lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
<div className="hidden md:block items-center gap-4 max-w-sm mx-auto lg:flex">
<Skeleton className="h-[73px] w-16 rounded-md" />
<div className="space-y-2">
<Skeleton className="h-4 w-[250px]" />
<Skeleton className="h-4 w-[200px]" />
</div>
</div>
</>
) : (
<ul className="py-4 lg:py-0 flex flex-row lg:flex-col gap-4 flex-nowrap w-[95vw] lg:w-auto overflow-x-auto">
{content?.map((item: any) => (
<li key={item?.id} className="flex gap-4 flex-row lg:w-full ">
<div className="flex-shrink-0 w-24 rounded-lg">
<Image width={720} height={480} src={item?.thumbnailLink} alt={item?.title} className="w-full h-[73px] object-cover rounded-lg" />
</div>
<div className="w-[280px] lg:w-auto">
<span className="text-white bg-[#bb3523] px-4 py-1 rounded-lg flex text-[8px] font-bold uppercase w-fit">{item?.categoryName}</span>
<Link
href={
Number(item?.fileType?.id) == 1
? `${asPath.includes("/polda/") == true ? asPath : ""}/image/detail/${item?.slug}`
: Number(item?.fileType?.id) == 2
? `/video/detail/${item?.slug}`
: Number(item?.fileType?.id) == 3
? `/document/detail/${item?.slug}`
: `/audio/detail/${item?.slug}`
}
>
<h3 className="text-base font-bold mt-2">{textEllipsis(item?.title, 30)}</h3>
</Link>
<p className="text-[10px] flex flex-row items-center gap-1 text-gray-500 mt-1">
{formatDateToIndonesian(new Date(item?.createdAt))} {item?.timezone ? item?.timezone : "WIB"} |{" "}
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24">
<path
fill="currentColor"
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
/>
</svg>{" "}
{item?.clickCount}
</p>
</div>
</li>
))}
</ul>
)}
</div>
</div> </div>
</div> </div>
); );

View File

@ -5,6 +5,7 @@ import { Link } from "@/i18n/routing";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { getInfoProfile, getListPorvinces, getUsersTeams } from "@/service/landing/landing"; import { getInfoProfile, getListPorvinces, getUsersTeams } from "@/service/landing/landing";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import { useTranslations } from "next-intl";
const HeaderManagement = () => { const HeaderManagement = () => {
const [profile, setProfile] = useState<any>(); const [profile, setProfile] = useState<any>();
@ -12,6 +13,7 @@ const HeaderManagement = () => {
const [, setUser] = useState(); const [, setUser] = useState();
const [selectedTab, setSelectedTab] = useState("video"); const [selectedTab, setSelectedTab] = useState("video");
const params = useParams(); const params = useParams();
const t = useTranslations("LandingPage");
// const currentRoute = router.pathname; // const currentRoute = router.pathname;
// const profilePicture = Cookies.get("profile_picture"); // const profilePicture = Cookies.get("profile_picture");
@ -67,24 +69,24 @@ const HeaderManagement = () => {
return ( return (
<div> <div>
{/* Header */} {/* Header */}
<div className="bg-[#504e52] p-10 lg:p-12"> <div className="bg-[#cccccc] p-5 lg:p-8">
<div className="flex flex-col lg:flex-row justify-center lg:justify-between mx-6 lg:mx-10"> <div className="flex flex-col lg:flex-row justify-center lg:justify-between mx-6 lg:mx-10">
<div className="flex items-center gap-2 "> <div className="flex items-center gap-2 ">
<img src="/assets/avatar-profile.png" alt="avatar" className="w-14 h-14" /> <img src="/assets/gg-profile.png" alt="avatar" className="w-14 h-14" />
<div className="flex flex-col mx-2"> <div className="flex flex-col mx-2">
<p className="text-white text-sm font-semibold">{profile?.fullname}</p> <p className="text-black text-sm font-semibold">{profile?.fullname}</p>
<p className="text-white text-sm font-light">{profile?.username}</p> <p className="text-black text-sm font-light">{profile?.username}</p>
<p className="text-white text-sm font-light"> <p className="text-black text-sm font-light">
Aktif Sejak&nbsp; {t("activeSince")}&nbsp;
{`${new Date(profile?.createdAt).getDate()}/${new Date(profile?.createdAt).getMonth() + 1}/${new Date(profile?.createdAt).getFullYear()} ${new Date(profile?.createdAt).getHours()}:${new Date( {`${new Date(profile?.createdAt).getDate()}/${new Date(profile?.createdAt).getMonth() + 1}/${new Date(profile?.createdAt).getFullYear()} ${new Date(profile?.createdAt).getHours()}:${new Date(
profile?.createdAt profile?.createdAt
).getMinutes()}`} ).getMinutes()}`}
</p> </p>
</div> </div>
</div> </div>
<Link href="/profile" className="flex justify-center items-center text-white gap-2 mt-3 lg:mt-0"> <Link href="/profile" className="flex justify-center items-center text-black gap-2 mt-3 lg:mt-0">
<Icon icon="tdesign:setting-1-filled" /> <p className="text-sm lg:text-base">{t("fullProfile")}</p>
<p className="text-sm lg:text-base">Pengaturan</p> <Icon icon="ri:arrow-right-s-line" className="h-5 w-5" />
</Link> </Link>
</div> </div>
</div> </div>

View File

@ -486,12 +486,12 @@ const Navbar = () => {
<DropdownMenuGroup> <DropdownMenuGroup>
{[ {[
{ {
name: "Profile & Settings", name: t("profileSetting"),
icon: "heroicons:user", icon: "heroicons:user",
href: "/profile", href: "/profile",
}, },
{ {
name: "Kelola Konten", name: t("contentManagement"),
icon: "stash:save-ribbon-duotone", icon: "stash:save-ribbon-duotone",
href: "/content-management/galery", href: "/content-management/galery",
}, },
@ -1058,12 +1058,12 @@ const Navbar = () => {
<DropdownMenuGroup> <DropdownMenuGroup>
{[ {[
{ {
name: "Profile & Settings", name: t("profileSetting"),
icon: "heroicons:user", icon: "heroicons:user",
href: "/profile", href: "/profile",
}, },
{ {
name: "Kelola Konten", name: t("contentManagement"),
icon: "stash:save-ribbon-duotone", icon: "stash:save-ribbon-duotone",
href: "/content-management/galery", href: "/content-management/galery",
}, },

View File

@ -5,6 +5,7 @@ import { getInfoProfile, getListPorvinces, getUsersTeams } from "@/service/landi
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import { useTranslations } from "next-intl";
const SidebarManagement = () => { const SidebarManagement = () => {
const [profile, setProfile] = useState<any>(); const [profile, setProfile] = useState<any>();
@ -13,6 +14,7 @@ const SidebarManagement = () => {
const [selectedTab, setSelectedTab] = useState("video"); const [selectedTab, setSelectedTab] = useState("video");
const params = useParams(); const params = useParams();
const pathname = usePathname(); const pathname = usePathname();
const t = useTranslations("LandingPage");
// const currentRoute = router.pathname; // const currentRoute = router.pathname;
// const profilePicture = Cookies.get("profile_picture"); // const profilePicture = Cookies.get("profile_picture");
@ -67,7 +69,7 @@ const SidebarManagement = () => {
return ( return (
<div className="p-4 lg:p-12 w-full lg:w-1/3 "> <div className="p-4 lg:p-12 w-full lg:w-1/3 ">
<div className="border rounded-2xl border-black m-4"> <div className="border rounded-2xl border-black m-4">
<h1 className="text-xl p-5">Tentang Saya</h1> <h1 className="text-xl p-5">{t("aboutMe")}</h1>
<div> <div>
<ul className="px-10 mb-4"> <ul className="px-10 mb-4">
<li className="mb-5 font-light"> <li className="mb-5 font-light">
@ -75,19 +77,19 @@ const SidebarManagement = () => {
<p>{profile?.email}</p> <p>{profile?.email}</p>
</li> </li>
<li className="mb-5 font-light"> <li className="mb-5 font-light">
<p className="font-semibold">No Handphone :</p> <p className="font-semibold">{t("number")} :</p>
<p>{profile?.phoneNumber}</p> <p>{profile?.phoneNumber}</p>
</li> </li>
<li className="mb-5 font-light"> <li className="mb-5 font-light">
<p className="font-semibold">Alamat :</p> <p className="font-semibold">{t("address")} :</p>
<p>{profile?.address}</p> <p>{profile?.address}</p>
</li> </li>
<li className="mb-5 font-light"> <li className="mb-5 font-light">
<p className="font-semibold">Kategori :</p> <p className="font-semibold">{t("category")} :</p>
<p>{profile?.institute?.categoryRole?.name}</p> <p>{profile?.institute?.categoryRole?.name}</p>
</li> </li>
<li className="mb-5 font-light"> <li className="mb-5 font-light">
<p className="font-semibold">Instansi/Perusahaan :</p> <p className="font-semibold">{t("company")} :</p>
<p>{profile?.institute?.name}</p> <p>{profile?.institute?.name}</p>
</li> </li>
</ul> </ul>
@ -99,7 +101,9 @@ const SidebarManagement = () => {
<div className={`${pathname?.includes("/content-management/galery") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}> <div className={`${pathname?.includes("/content-management/galery") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}>
<div className="flex items-center gap-2 text-lg"> <div className="flex items-center gap-2 text-lg">
<Icon icon="material-symbols-light:perm-media-rounded" /> <Icon icon="material-symbols-light:perm-media-rounded" />
<p className="text-sm">Galeri {profile?.institute?.name}</p> <p className="text-sm">
{t("gallery")} {profile?.institute?.name}
</p>
</div> </div>
<div> <div>
<Icon icon="ri:arrow-right-s-line" fontSize={20} /> <Icon icon="ri:arrow-right-s-line" fontSize={20} />
@ -110,7 +114,7 @@ const SidebarManagement = () => {
<div className={`${pathname?.includes("/content-management/download") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}> <div className={`${pathname?.includes("/content-management/download") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}>
<div className="flex items-center gap-2 text-lg"> <div className="flex items-center gap-2 text-lg">
<Icon icon="heroicons:photo-solid" /> <Icon icon="heroicons:photo-solid" />
<p className="text-sm">Galeri Saya</p> <p className="text-sm">{t("myGallery")} </p>
</div> </div>
<div> <div>
<Icon icon="ri:arrow-right-s-line" fontSize={20} /> <Icon icon="ri:arrow-right-s-line" fontSize={20} />
@ -121,7 +125,7 @@ const SidebarManagement = () => {
<div className={`${pathname?.includes("/content-management/rewrite") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}> <div className={`${pathname?.includes("/content-management/rewrite") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}>
<div className="flex items-center gap-2 text-lg"> <div className="flex items-center gap-2 text-lg">
<Icon icon="material-symbols-light:perm-media-rounded" /> <Icon icon="material-symbols-light:perm-media-rounded" />
<p className="text-sm">Galeri Rewrite</p> <p className="text-sm">{t("gallery")} Rewrite</p>
</div> </div>
<div> <div>
<Icon icon="ri:arrow-right-s-line" fontSize={20} /> <Icon icon="ri:arrow-right-s-line" fontSize={20} />
@ -132,7 +136,7 @@ const SidebarManagement = () => {
<div className={`${pathname?.includes("/content-management/users") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}> <div className={`${pathname?.includes("/content-management/users") ? "bg-slate-500 text-white" : ""} hover:bg-slate-500 hover:text-white cursor-pointer p-4 rounded-lg flex justify-between`}>
<div className="flex items-center gap-2 text-lg"> <div className="flex items-center gap-2 text-lg">
<Icon icon="mdi:users-group" /> <Icon icon="mdi:users-group" />
<p className="text-sm">Tim Pengguna</p> <p className="text-sm">{t("userTeam")}</p>
</div> </div>
<div> <div>
<Icon icon="ri:arrow-right-s-line" fontSize={20} /> <Icon icon="ri:arrow-right-s-line" fontSize={20} />

View File

@ -3,6 +3,8 @@ import React, { useEffect, useState } from "react";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu";
import { FiFile, FiImage, FiMusic, FiYoutube } from "react-icons/fi"; import { FiFile, FiImage, FiMusic, FiYoutube } from "react-icons/fi";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { useTranslations } from "next-intl";
import { Input } from "../ui/input";
const WelcomePolda = () => { const WelcomePolda = () => {
const router = useRouter(); const router = useRouter();
@ -10,7 +12,7 @@ const WelcomePolda = () => {
const params = useParams(); const params = useParams();
const poldaName: any = params?.polda_name; const poldaName: any = params?.polda_name;
const [categorySelect, setCategorySelect] = useState("0"); const [categorySelect, setCategorySelect] = useState("0");
const [search, setSearch] = useState(); const t = useTranslations("LandingPage");
useEffect(() => { useEffect(() => {
function initState() { function initState() {
@ -25,11 +27,11 @@ const WelcomePolda = () => {
<div className="max-w-screen-xl mx-auto text-center"> <div className="max-w-screen-xl mx-auto text-center">
{/* Heading */} {/* Heading */}
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white"> <h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
Selamat Datang di <span className="text-[#bb3523] dark:text-white">Polda</span> <span className="capitalize">{poldaName.replace("-", " ")}</span> {t("welcome")} <span className="text-[#bb3523] dark:text-white">Polda</span> <span className="capitalize">{poldaName.replace("-", " ")}</span>
</h1> </h1>
<div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div> <div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div>
<p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4"> <p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4">
Liputan resmi yang bersumber dari kegiatan Polri di Polda <span className="capitalize">{poldaName.replace("-", " ")}</span> {t("polda")} <span className="capitalize">{poldaName.replace("-", " ")}</span>
</p> </p>
{/* Search Form */} {/* Search Form */}
@ -45,7 +47,7 @@ const WelcomePolda = () => {
fill="currentColor" fill="currentColor"
/> />
</svg> </svg>
Konten {t("content")}
<svg className="flex items-center justify-center" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"> <svg className="flex items-center justify-center" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="m6 7l6 6l6-6l2 2l-8 8l-8-8z" /> <path fill="currentColor" fill-rule="evenodd" d="m6 7l6 6l6-6l2 2l-8 8l-8-8z" />
</svg> </svg>
@ -55,25 +57,25 @@ const WelcomePolda = () => {
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700c flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700c flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiYoutube className="mr-2" /> <FiYoutube className="mr-2" />
Audio Visual {t("video")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiMusic className="mr-2" /> <FiMusic className="mr-2" />
Audio {t("audio")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiImage className="mr-2" /> <FiImage className="mr-2" />
Foto {t("image")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiFile className="mr-2" /> <FiFile className="mr-2" />
Teks {t("text")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
@ -87,15 +89,13 @@ const WelcomePolda = () => {
/> />
</svg> </svg>
</span> </span>
<input type="text" placeholder="Pencarian" className="w-full py-2 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none" /> <Input type="text" placeholder={t("search")} className="w-full py-2 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none" />
</div> </div>
</div> </div>
{/* Search Input */}
{/* Button */} {/* Button */}
<button className="flex justify-center items-center px-6 w-full lg:w-[20%] py-2 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700"> <button className="flex justify-center items-center px-6 w-full lg:w-[20%] py-2 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700">
Cari Liputan <Icon icon="ri:arrow-right-s-line" fontSize={20} /> {t("searchCoverage")} <Icon icon="ri:arrow-right-s-line" fontSize={20} />
</button> </button>
</div> </div>
</div> </div>

View File

@ -5,7 +5,7 @@ import React, { useEffect, useState } from "react";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu";
import { FiFile, FiImage, FiMusic, FiYoutube } from "react-icons/fi"; import { FiFile, FiImage, FiMusic, FiYoutube } from "react-icons/fi";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { capitalize } from "@/utils/globals"; import { useTranslations } from "next-intl";
const WelcomeSatker = () => { const WelcomeSatker = () => {
const router = useRouter(); const router = useRouter();
@ -13,7 +13,7 @@ const WelcomeSatker = () => {
const params = useParams(); const params = useParams();
const satkerName: any = params?.satker_name; const satkerName: any = params?.satker_name;
const [categorySelect, setCategorySelect] = useState("0"); const [categorySelect, setCategorySelect] = useState("0");
const [search, setSearch] = useState(); const t = useTranslations("LandingPage");
useEffect(() => { useEffect(() => {
function initState() { function initState() {
@ -28,11 +28,11 @@ const WelcomeSatker = () => {
<div className="max-w-screen-xl mx-auto text-center"> <div className="max-w-screen-xl mx-auto text-center">
{/* Heading */} {/* Heading */}
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white"> <h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
Selamat Datang di <span className="text-[#bb3523] dark:text-white">Satker</span> <span className="capitalize">{satkerName.replace("-", " ")}</span> {t("welcome")} <span className="text-[#bb3523] dark:text-white">Satker</span> <span className="capitalize">{satkerName.replace("-", " ")}</span>
</h1> </h1>
<div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div> <div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div>
<p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4"> <p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4">
Liputan resmi yang bersumber dari kegiatan Polri di Satker <span className="capitalize">{satkerName.replace("-", " ")}</span> {t("satker")} <span className="capitalize">{satkerName.replace("-", " ")}</span>
</p> </p>
{/* Search Form */} {/* Search Form */}
@ -48,7 +48,7 @@ const WelcomeSatker = () => {
fill="currentColor" fill="currentColor"
/> />
</svg> </svg>
Konten {t("content")}
<svg className="flex items-center justify-center" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"> <svg className="flex items-center justify-center" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="m6 7l6 6l6-6l2 2l-8 8l-8-8z" /> <path fill="currentColor" fill-rule="evenodd" d="m6 7l6 6l6-6l2 2l-8 8l-8-8z" />
</svg> </svg>
@ -58,25 +58,25 @@ const WelcomeSatker = () => {
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700c flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700c flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiYoutube className="mr-2" /> <FiYoutube className="mr-2" />
Audio Visual {t("video")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiMusic className="mr-2" /> <FiMusic className="mr-2" />
Audio {t("audio")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiImage className="mr-2" /> <FiImage className="mr-2" />
Foto {t("image")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group"> <DropdownMenuItem className="flex items-center gap-1.5 p-2 border-b text-default-600 group focus:bg-default focus:text-primary-foreground rounded-none group">
<span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground"> <span className="text-default-700 flex flex-row justify-center items-center group-hover:text-primary-foreground">
<FiFile className="mr-2" /> <FiFile className="mr-2" />
Teks {t("text")}
</span> </span>
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
@ -90,15 +90,13 @@ const WelcomeSatker = () => {
/> />
</svg> </svg>
</span> </span>
<input type="text" placeholder="Pencarian" className="w-full py-2 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none" /> <input type="text" placeholder={t("search")} className="w-full py-2 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none" />
</div> </div>
</div> </div>
{/* Search Input */}
{/* Button */} {/* Button */}
<button className="flex justify-center items-center px-6 w-full lg:w-[20%] py-2 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700"> <button className="flex justify-center items-center px-6 w-full lg:w-[20%] py-2 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700">
Cari Liputan <Icon icon="ri:arrow-right-s-line" fontSize={20} /> {t("searchCoverage")} <Icon icon="ri:arrow-right-s-line" fontSize={20} />
</button> </button>
</div> </div>
</div> </div>

View File

@ -454,7 +454,70 @@
"addressInst": "Input the complete address of your institution", "addressInst": "Input the complete address of your institution",
"identityEmpty": "Identity number cannot be empty", "identityEmpty": "Identity number cannot be empty",
"policeNumber": "Police Registration Number", "policeNumber": "Police Registration Number",
"breakingNews": "BREAKING NEWS" "breakingNews": "BREAKING NEWS",
"changeProfile": "Change Profile",
"userProfile": "User Profile",
"changePhoto": "Change Photo",
"changePass": "Change Password",
"pleaseChange": "Please change your personal data in the following form.",
"identityNumber": "Identity Number",
"noImage": "No Image",
"deletePhoto": "Delete Photo",
"activeSince": "Active since",
"fullProfile": "View full profile",
"aboutMe": "About Me",
"company": "Agency/Company",
"gallery": "Gallery",
"myGallery": "My Gallery",
"userTeam": "User Team",
"my": "My",
"team": "Team",
"teamMembers": "Team Members",
"reasonReport": "Reasons for Reporting Account",
"saveData": "Save Data ?",
"language": "Language",
"selectLanguage": "Select Language",
"contextType": "Context Type",
"selectContext": "Select Context",
"article": "Article",
"transcript": "Transcript",
"writingStyle": "Writing Style",
"selectWriting": "Select Writing Style",
"articleSize": "Article Size",
"selectSize": "Select Size",
"title": "Title",
"mainKeyword": "Main Keyword",
"newDescription": "New Description",
"back": "Back",
"notifList": "Notification List",
"userFeedback": "User Feedback",
"ratings": "Please provide your rating regarding the ease of access to the MediaHUB Polri website.",
"ratings2": "Please give your rating regarding the appearance of the MediaHUB Polri website.",
"ratings3": "Please give your rating regarding the content of MediaHUB Polri",
"contactUs": "Contact Us",
"writeMessage": "Write a Message",
"leaveMessage": "Please leave your message in the column provided",
"name": "Name",
"subject": "Subject",
"selectSubject": "Select Subject",
"question": "Question",
"criticism": "Criticism",
"suggestion": "Suggestion",
"messages": "Messages",
"profileSetting": "Profile & Settings",
"enterName": "Enter your full name",
"writeYourMessage": "Write your message",
"question1": "WHAT CONTENT IS ON MEDIAHUB AND WHAT CATEGORIES ARE THERE IN IT?",
"answer1": "MediaHub has a variety of content such as news, videos, and documents categorized into topics such as education, entertainment, and current affairs.",
"question2": "HOW CAN MEDIAHUB CONTENT BE DOWNLOADED?",
"answer2": "You can download content by clicking the download button available on each content on the MediaHub page.",
"question3": "WHO CAN REGISTER AS A MEDIAHUB USER?",
"answer3": "Anyone who has an interest in the content on MediaHub can register as a user, either for personal or professional purposes.",
"question4": "WHAT IS MEDIAHUB? AND WHAT ARE THE FEATURES IN IT?",
"answer4": "MediaHub is a platform that provides various informative and educational content. Key features include search, download, and personalization of content.",
"welcome": "Welcome To",
"polda": "Official coverage sourced from Polri activities at Polda",
"satker": "Official coverage sourced from Polri activities at Satker"
}, },
"FilterPage": { "FilterPage": {
"image": "Image", "image": "Image",

View File

@ -370,7 +370,7 @@
"updatedOn": "Diupdate pada", "updatedOn": "Diupdate pada",
"creator": "Kreator :", "creator": "Kreator :",
"delete": "Hapus", "delete": "Hapus",
"imageSize": "Opsi Ukuran Poto", "imageSize": "Opsi Ukuran Foto",
"downloadAll": "Download Semua File?", "downloadAll": "Download Semua File?",
"share": "Bagikan", "share": "Bagikan",
"shareTo": "Bagikan ke Email", "shareTo": "Bagikan ke Email",
@ -409,7 +409,7 @@
"fullName": "Nama Lengkap", "fullName": "Nama Lengkap",
"enterFullName": "Masukkan Nama Lengkap Anda", "enterFullName": "Masukkan Nama Lengkap Anda",
"enterUsername": "Masukkan Username Anda", "enterUsername": "Masukkan Username Anda",
"number": "Nomor Telepon", "number": "Nomor Handphone",
"enterNumber": "Masukkan Nomor Telepon Anda", "enterNumber": "Masukkan Nomor Telepon Anda",
"enterEmail": "Masukkan Email Anda", "enterEmail": "Masukkan Email Anda",
"address": "Alamat", "address": "Alamat",
@ -454,8 +454,70 @@
"addressInst": "Masukkan Alamat lengkap institusi anda", "addressInst": "Masukkan Alamat lengkap institusi anda",
"identityEmpty": "Nomor identitas tidak boleh kosong", "identityEmpty": "Nomor identitas tidak boleh kosong",
"policeNumber": "Nomor Registrasi Polri (NRP)", "policeNumber": "Nomor Registrasi Polri (NRP)",
"breakingNews": "BERITA TERKINI" "breakingNews": "BERITA TERKINI",
"changeProfile": "Ubah Profil",
"userProfile": "Profil Pengguna",
"changePhoto": "Ubah Foto",
"changePass": "Ubah Password",
"pleaseChange": "Silahkan ubah data pribadi Anda pada form berikut.",
"identityNumber": "Nomor Identitas",
"noImage": "Tanpa Foto",
"deletePhoto": "Hapus Foto",
"activeSince": "Aktif Sejak",
"fullProfile": "Lihat profil lengkap",
"aboutMe": "Tentang Saya",
"company": "Instansi/Perusahaan",
"gallery": "Galeri",
"myGallery": "Galeri Saya",
"userTeam": "Tim Pengguna",
"my": "Saya",
"team": "Tim",
"teamMembers": "Anggota Tim",
"reasonReport": "Alasan Report Akun",
"saveData": "Simpan Data ?",
"language": "Bahasa",
"selectLanguage": "Pilih Bahasa",
"contextType": "Jenis Konteks",
"selectContext": "Pilih Konteks",
"article": "Artikel",
"transcript": "Transkrip",
"writingStyle": "Gaya Penulisan",
"selectWriting": "Pilih Gaya Penulisan",
"articleSize": "Ukuran Artikel",
"selectSize": "Pilih Ukuran Artikel",
"title": "Judul",
"mainKeyword": "Kata Kunci",
"newDescription": "Deskripsi Baru",
"back": "Kembali",
"notifList": "List Notifikasi",
"userFeedback": "Feedback Pengguna",
"ratings": "Silakan berikan rating Anda terkait dengan kemudahan akses website MediaHUB Polri.",
"ratings2": "Silakan berikan rating Anda terkait dengan tampilan website MediaHUB Polri.",
"ratings3": "Silahkan berikan rating Anda terkait dengan konten MediaHUB Polri.",
"contactUs": "Hubungi Kami",
"writeMessage": "Tulis Pesan",
"leaveMessage": "Silahkan tinggalkan pesan Anda pada kolom yang tersedia.",
"name": "Nama",
"subject": "Subjek",
"selectSubject": "Pilih Subjek",
"question": "Pertanyaan",
"criticism": "Kritik",
"suggestion": "Saran",
"messages": "Pesan",
"profileSetting": "Profil & Pengaturan",
"enterName": "Masukkan Nama Lengkap Anda",
"writeYourMessage": "Write your message",
"question1": "APA SAJA KONTEN-KONTEN YANG ADA DI MEDIAHUB DAN KATEGORI DI DALAMNYA?",
"answer1": "MediaHub memiliki beragam konten seperti berita, video, dan dokumen yang dikategorikan dalam topik seperti edukasi, hiburan, dan informasi terkini.",
"question2": "BAGAIMANA KONTEN DARI MEDIAHUB DAPAT DIUNDUH?",
"answer2": "Anda dapat mengunduh konten dengan klik tombol unduh yang tersedia pada setiap konten di halaman MediaHub.",
"question3": "SIAPA SAJA YANG DAPAT MENDAFTARKAN DIRI SEBAGAI PENGGUNA MEDIAHUB?",
"answer3": "Semua orang yang memiliki minat terhadap konten di MediaHub dapat mendaftar sebagai pengguna, baik untuk personal maupun profesional.",
"question4": "APA ITU MEDIAHUB? DAN APA SAJA FITUR YANG ADA DI DALAMNYA?",
"answer4": "MediaHub adalah platform yang menyediakan berbagai konten informatif dan edukatif. Fitur utama meliputi pencarian, pengunduhan, dan personalisasi konten.",
"welcome": "Selamat Datang di",
"polda": "Liputan resmi yang bersumber dari kegiatan Polri di Polda",
"satker": "Liputan resmi yang bersumber dari kegiatan Polri di Satker"
}, },
"FilterPage": { "FilterPage": {
"image": "Foto", "image": "Foto",

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

View File

@ -63,6 +63,11 @@ export async function getProfile(token: any) {
return httpGetInterceptorWithToken(url, token); return httpGetInterceptorWithToken(url, token);
} }
export async function getSubjects() {
const url = 'inbox/subjects';
return httpGetInterceptor( url );
}
export async function getInfoProfile() { export async function getInfoProfile() {
const url = "users/info"; const url = "users/info";
return httpGetInterceptor(url); return httpGetInterceptor(url);

View File

@ -200,3 +200,8 @@ export async function deleteBlogComments(slug: any) {
const url = `blog/comments?id=${slug}`; const url = `blog/comments?id=${slug}`;
return httpDeleteInterceptor(url); return httpDeleteInterceptor(url);
} }
export async function sendMessage(data: any) {
const url = 'inbox';
return httpPostInterceptor( url, data );
}

View File

@ -8,11 +8,7 @@ export const generateLocalizedPath = (href: string, locale: string): string => {
return `/${locale}${href}`; return `/${locale}${href}`;
}; };
export function textEllipsis( export function textEllipsis(str: string, maxLength: number, { side = "end", ellipsis = "..." } = {}) {
str: string,
maxLength: number,
{ side = "end", ellipsis = "..." } = {}
) {
if (str !== undefined && str?.length > maxLength) { if (str !== undefined && str?.length > maxLength) {
switch (side) { switch (side) {
case "start": case "start":
@ -27,7 +23,7 @@ export function textEllipsis(
export function formatDateToIndonesian(d: Date) { export function formatDateToIndonesian(d: Date) {
try { try {
const dateString = format(d, "d MMMM yyyy HH:mm", { locale: id }); const dateString = format(d, "d/MM/yy HH:mm", { locale: id });
return dateString; return dateString;
} catch (error) { } catch (error) {
return ""; return "";
@ -64,6 +60,14 @@ export function getOnlyDate(date: Date) {
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
} }
export function getOnlyDateSlash(date: Date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${day}/${month}/${year}`;
}
export function getOnlyMonthAndYear(d: Date) { export function getOnlyMonthAndYear(d: Date) {
const pad = (n: any, s = 2) => `${new Array(s).fill(0)}${n}`.slice(-s); const pad = (n: any, s = 2) => `${new Array(s).fill(0)}${n}`.slice(-s);
return `${pad(d.getMonth() + 1)}/${pad(d.getFullYear(), 4)}`; return `${pad(d.getMonth() + 1)}/${pad(d.getFullYear(), 4)}`;
@ -71,10 +75,7 @@ export function getOnlyMonthAndYear(d: Date) {
export function getPublicLocaleTimestamp(d: any) { export function getPublicLocaleTimestamp(d: any) {
const pad = (n: any, s = 2) => `${new Array(s).fill(0)}${n}`.slice(-s); const pad = (n: any, s = 2) => `${new Array(s).fill(0)}${n}`.slice(-s);
return `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${pad( return `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${pad(d.getFullYear(), 4)} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
d.getFullYear(),
4
)} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
} }
export function capitalize(s: any) { export function capitalize(s: any) {
@ -87,13 +88,9 @@ export function capitalize(s: any) {
} }
export function getLocaleTimestamp(d: Date): string { export function getLocaleTimestamp(d: Date): string {
const pad = (n: number, s: number = 2): string => const pad = (n: number, s: number = 2): string => `${new Array(s).fill(0)}${n}`.slice(-s);
`${new Array(s).fill(0)}${n}`.slice(-s);
return `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${pad( return `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${pad(d.getFullYear(), 4)} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
d.getFullYear(),
4
)} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
} }
export function getLocaleTime(d: Date) { export function getLocaleTime(d: Date) {
@ -102,9 +99,7 @@ export function getLocaleTime(d: Date) {
} }
export function getTimestamp(d: Date) { export function getTimestamp(d: Date) {
const pad = (n: any, s = 2) => `${new Array(s).fill(0)}${n}`.slice(-s); const pad = (n: any, s = 2) => `${new Array(s).fill(0)}${n}`.slice(-s);
return `${pad(d.getFullYear(), 4)}-${pad(d.getMonth() + 1)}-${pad( return `${pad(d.getFullYear(), 4)}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
d.getDate()
)} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
} }
export function secondToTimes(sec: number) { export function secondToTimes(sec: number) {
@ -118,10 +113,7 @@ export function secondToTimes(sec: number) {
export function checkMaliciousText(str: any) { export function checkMaliciousText(str: any) {
try { try {
const urlPattern = new RegExp( const urlPattern = new RegExp("(https?:\\/\\/(?:www\\.|(?!www))[^\\s\\.]+\\.[^\\s]{2,}|www\\.[^\\s]+\\.[^\\s]{2,}|https?:\\/\\/[^\\s]+|\\b(?:https?|ftp):\\/\\/[^\\s/$.?#].[^\\s]*)", "gi");
"(https?:\\/\\/(?:www\\.|(?!www))[^\\s\\.]+\\.[^\\s]{2,}|www\\.[^\\s]+\\.[^\\s]{2,}|https?:\\/\\/[^\\s]+|\\b(?:https?|ftp):\\/\\/[^\\s/$.?#].[^\\s]*)",
"gi"
);
const isContainUrl = urlPattern.test(str); const isContainUrl = urlPattern.test(str);
if (isContainUrl) { if (isContainUrl) {
return "Message mengandung URL yang tidak diizinkan"; return "Message mengandung URL yang tidak diizinkan";