diff --git a/Dockerfile b/Dockerfile index 1786122..7911d44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:21-alpine +FROM node:23.5.0-alpine ENV PORT 4000 @@ -10,7 +10,7 @@ WORKDIR /usr/src/app COPY package*.json /usr/src/app/ # RUN npm install --force -# RUN npm install -g npm@latest +RUN npm install -g npm@latest RUN npm install # Copying source files diff --git a/app/(admin)/admin/article/create/page.tsx b/app/(admin)/admin/article/create/page.tsx index a12f045..836116f 100644 --- a/app/(admin)/admin/article/create/page.tsx +++ b/app/(admin)/admin/article/create/page.tsx @@ -4,7 +4,7 @@ import { Card } from "@nextui-org/react"; export default function CreateArticle() { return ( -
+
{/* */}
diff --git a/app/(admin)/admin/article/detail/[id]/page.tsx b/app/(admin)/admin/article/detail/[id]/page.tsx index 9b5cbcd..d3b68e0 100644 --- a/app/(admin)/admin/article/detail/[id]/page.tsx +++ b/app/(admin)/admin/article/detail/[id]/page.tsx @@ -2,7 +2,7 @@ import EditArticleForm from "@/components/form/article/edit-article-form"; export default function DetailArticlePage() { return ( -
+
{/* */}
diff --git a/app/(admin)/admin/article/edit/[id]/page.tsx b/app/(admin)/admin/article/edit/[id]/page.tsx index 3586d72..93ffc72 100644 --- a/app/(admin)/admin/article/edit/[id]/page.tsx +++ b/app/(admin)/admin/article/edit/[id]/page.tsx @@ -2,7 +2,7 @@ import EditArticleForm from "@/components/form/article/edit-article-form"; export default function UpdateArticlePage() { return ( -
+
); diff --git a/app/(admin)/admin/article/page.tsx b/app/(admin)/admin/article/page.tsx index c8c8fbd..935f32b 100644 --- a/app/(admin)/admin/article/page.tsx +++ b/app/(admin)/admin/article/page.tsx @@ -10,9 +10,12 @@ export default function BasicPage() { return (
-
- - diff --git a/app/(admin)/admin/dashboard/page.tsx b/app/(admin)/admin/dashboard/page.tsx index acba2e7..3be562d 100644 --- a/app/(admin)/admin/dashboard/page.tsx +++ b/app/(admin)/admin/dashboard/page.tsx @@ -3,7 +3,7 @@ import DashboardContainer from "@/components/main/dashboard/dashboard-container" export default function AdminPage() { return (
-
+
diff --git a/app/(admin)/admin/magazine/create/page.tsx b/app/(admin)/admin/magazine/create/page.tsx index a5f5009..9ad1486 100644 --- a/app/(admin)/admin/magazine/create/page.tsx +++ b/app/(admin)/admin/magazine/create/page.tsx @@ -4,7 +4,7 @@ import React from "react"; const AdminMagazineCreate = () => { return ( -
+
); diff --git a/app/(admin)/admin/magazine/detail/[id]/page.tsx b/app/(admin)/admin/magazine/detail/[id]/page.tsx index 058b325..a948b2e 100644 --- a/app/(admin)/admin/magazine/detail/[id]/page.tsx +++ b/app/(admin)/admin/magazine/detail/[id]/page.tsx @@ -2,7 +2,7 @@ import EditMagazineForm from "@/components/form/magazine/edit-magazine-form"; export default function DetailArticlePage() { return ( -
+
); diff --git a/app/(admin)/admin/magazine/edit/[id]/page.tsx b/app/(admin)/admin/magazine/edit/[id]/page.tsx index d956702..dd20cc7 100644 --- a/app/(admin)/admin/magazine/edit/[id]/page.tsx +++ b/app/(admin)/admin/magazine/edit/[id]/page.tsx @@ -2,7 +2,7 @@ import EditMagazineForm from "@/components/form/magazine/edit-magazine-form"; export default function EditArticlePage() { return ( -
+
); diff --git a/app/(admin)/admin/magazine/page.tsx b/app/(admin)/admin/magazine/page.tsx index cf6a5d1..1bee7e5 100644 --- a/app/(admin)/admin/magazine/page.tsx +++ b/app/(admin)/admin/magazine/page.tsx @@ -8,9 +8,12 @@ export default function MagazineTablePage() { return (
-
- - diff --git a/app/(admin)/admin/master-category/page.tsx b/app/(admin)/admin/master-category/page.tsx index 250292f..b79b23b 100644 --- a/app/(admin)/admin/master-category/page.tsx +++ b/app/(admin)/admin/master-category/page.tsx @@ -164,10 +164,10 @@ export default function MasterCategoryTable() { return (
-
+
+ {detailfiles?.map((file: any, index: number) => ( +
+
+
+ {`image-${index}`}
- ) - )} +
+
+ {file?.file_name} +
+
+ {Math.round(file?.size / 100) / 10 > 1000 ? ( + <>{(Math.round(file?.size / 100) / 10000).toFixed(1)} + ) : ( + <>{(Math.round(file?.size / 100) / 10).toFixed(1)} + )} + {" kb"} +
+
+
+ + +
+ ))}
)}
-
+

Thubmnail

{isDetail ? ( - thumbnail + thumbnail ) : selectedMainImage && files.length >= selectedMainImage ? (
- thumbnail ) : thumbnail !== "" ? (
- thumbnail + thumbnail +
+ {articleIds.length > 0 && ( +
+ {articleIds?.map((id) => ( + + ))} +
+ )} + + + ); +} diff --git a/components/form/article/generate-ai-single-form.tsx b/components/form/article/generate-ai-single-form.tsx index c3289b2..f32d23e 100644 --- a/components/form/article/generate-ai-single-form.tsx +++ b/components/form/article/generate-ai-single-form.tsx @@ -388,7 +388,7 @@ export default function GenerateSingleArticleForm(props: {
{articleIds.length > 0 && (
- {articleIds?.map((id) => ( + {articleIds?.map((id, index) => ( ))} diff --git a/components/form/login.tsx b/components/form/login.tsx index 8e808d0..142ef14 100644 --- a/components/form/login.tsx +++ b/components/form/login.tsx @@ -10,6 +10,7 @@ import { checkUsernames, getProfile, postSignIn } from "@/service/master-user"; import { useRouter } from "next/navigation"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; +import { saveActivity } from "@/service/activity-log"; export default function Login() { const router = useRouter(); @@ -53,6 +54,14 @@ export default function Login() { sameSite: "strict", }); const profile = await getProfile(access_token); + const resActivity = await saveActivity( + { + activityTypeId: 1, + url: "https://kontenhumas.com/auth", + userId: profile?.data?.data?.id, + }, + response?.data?.data?.id_token + ); console.log("PROFILE : ", profile?.data); Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, { expires: 1, @@ -85,8 +94,8 @@ export default function Login() { expires: 1, }); - close(); router.push("/admin/dashboard"); + close(); Cookies.set("status", "login", { expires: 1, }); diff --git a/components/form/magazine/create-magazine-form.tsx b/components/form/magazine/create-magazine-form.tsx index 7cc3b5c..700751e 100644 --- a/components/form/magazine/create-magazine-form.tsx +++ b/components/form/magazine/create-magazine-form.tsx @@ -254,7 +254,7 @@ export default function NewCreateMagazineForm() {
{renderPreview(file)}
-
+

Nama File

{file.name}

@@ -389,7 +389,9 @@ export default function NewCreateMagazineForm() { {thumbnailImg.length > 0 ? (
- thumbnail @@ -446,7 +448,9 @@ export default function NewCreateMagazineForm() {
{files.length ? ( -
{fileList}
+
+ {fileList} +
{files.length > 1 && (
+
); } diff --git a/components/landing/BodyLayout.tsx b/components/landing/BodyLayout.tsx index 9d8c9ad..18ea54c 100644 --- a/components/landing/BodyLayout.tsx +++ b/components/landing/BodyLayout.tsx @@ -11,9 +11,9 @@ export default function BodyLayout() { <>
- {/* */} - {/* */} + +
diff --git a/components/landing/CategorySatker.tsx b/components/landing/CategorySatker.tsx index 1b75caa..ddd9a0e 100644 --- a/components/landing/CategorySatker.tsx +++ b/components/landing/CategorySatker.tsx @@ -53,6 +53,12 @@ export default function CategorySatker() { title: "Itwasum", path: "/news/itwasum", }, + { + id: 6, + img: "/assets/satker2/stik-ptik.svg", + title: "STIK-PTIK", + path: "/news/stik-ptik", + }, ]; const SatkerAll = [ @@ -298,18 +304,26 @@ export default function CategorySatker() { // }; // }, [list]); + const changeNameToSlug = (name: string) => { + const cleaned = name.trim().toLowerCase(); + return cleaned.replace(/\s+/g, "-"); + }; + return (
-
- {t("kategoriSatker")} +
+

+ {" "} + {t("kategoriSatker")} +

-
- -
-
+
{list.map((item: any, index: any) => ( - +
))}
-
- -
@@ -346,8 +358,12 @@ export default function CategorySatker() { {(onClose) => ( <> - - {t("kategoriSatker")} + +
+

+ {t("kategoriSatker")} +

+
{SatkerAll.map((item: any, index: any) => ( @@ -355,21 +371,31 @@ export default function CategorySatker() { key={index.id} className="w-[140px] h-[115px] flex flex-col items-center justify-center rounded-lg shadow-sm" > - + + {" "} -

+

{item.title}

))} - diff --git a/components/landing/ENewsPolri.tsx b/components/landing/ENewsPolri.tsx index a8200bb..b4d6040 100644 --- a/components/landing/ENewsPolri.tsx +++ b/components/landing/ENewsPolri.tsx @@ -69,8 +69,14 @@ export default function ENewsPolri() { thumbnail @@ -81,7 +87,6 @@ export default function ENewsPolri() {

- {" "}

{convertDateFormat(newsItem.createdAt)} WIB

diff --git a/components/landing/HeaderNews.tsx b/components/landing/HeaderNews.tsx index 737af1f..ca093e3 100644 --- a/components/landing/HeaderNews.tsx +++ b/components/landing/HeaderNews.tsx @@ -69,9 +69,15 @@ export default function HeaderNews() { {article?.map((newsItem: any) => ( - headernews @@ -111,10 +117,16 @@ export default function HeaderNews() { className="text-xs text-left m-2 p-2 dark:bg-[#1E1616] bg-white rounded-md flex flex-row gap-2" key={data.id} > - headernews
- {data.title}{" "} + {textEllipsis(data.title, 66)}

@@ -191,10 +203,16 @@ export default function HeaderNews() { radius="lg" className="border-none h-[67vh] shadow-none" > - headernews @@ -202,7 +220,7 @@ export default function HeaderNews() { -

+

{newsItem.title}

diff --git a/components/landing/MediaSocial.tsx b/components/landing/MediaSocial.tsx index 4194a89..e064497 100644 --- a/components/landing/MediaSocial.tsx +++ b/components/landing/MediaSocial.tsx @@ -1,111 +1,140 @@ import Link from "next/link"; import { ChevronRightIcon, + FacebookLandingIcon, FbIcon, IgIcon, + InstagramLandingIcon, + TiktokLandingIcon, TtIcon, TwitterIcon, + XLandingIcon, + YoutubeLandingIcon, YtIcon, } from "../icons"; import TwitterWidget from "../ui/social-media/twitter"; import InstagramWidget from "../ui/social-media/instagram"; import FacebookWidget from "../ui/social-media/facebook"; import YoutubeWidget from "../ui/social-media/youtube"; +import { useState } from "react"; +import { Button } from "@nextui-org/button"; export default function MediaSocial() { // const [limitedData, setLimitedData] = useState([]); - - const dummyData = [ - { - id: 1, - logo: "/logohumas.png", - division: "Divisi Humas Polri", - type: "/temp/offical.svg", - username: "@DivHumas_Polri", - followIcon: "/temp/iconX.svg", - description: - "Pada pembukaan KTT ke-43 ASEAN, Presiden RI, H. Joko Widodo menegaskan bahwa kesatuan ASEAN sampai saat ini masih terjaga dan terpelihara dengan baik.", - imageUrl: "/headernews.png", - }, - { - id: 2, - logo: "/logohumas.png", - division: "Divisi Humas Polri", - username: "@DivHumas_Polri", - type: "/temp/offical.svg", - followIcon: "/temp/iconX.svg", - description: - "Pada pembukaan KTT ke-43 ASEAN, Presiden RI, H. Joko Widodo menegaskan bahwa kesatuan ASEAN sampai saat ini masih terjaga dan terpelihara dengan baik.", - imageUrl: "/headernews.png", - }, - { - id: 3, - logo: "/logohumas.png", - division: "Divisi Humas Polri", - type: "/temp/offical.svg", - username: "@DivHumas_Polri", - followIcon: "/temp/iconX.svg", - description: - "Pada pembukaan KTT ke-43 ASEAN, Presiden RI, H. Joko Widodo menegaskan bahwa kesatuan ASEAN sampai saat ini masih terjaga dan terpelihara dengan baik.", - imageUrl: "/headernews.png", - }, - ]; + const [selectedPlatform, setSelectedPlatform] = useState("x"); return (

MediaSocial

-
-
+ +
+
-
- -
+ + + + +
-
-
-
- -

Instagram

-
-
-
- -
+
+
-
-
-
- -

Facebook

-
-
+
+ +
+
-
-
-
- -

Tiktok

-
-
+
-
-
-
- -

Youtube

-
-
-
- -
+
+
); diff --git a/components/landing/MedolUpdate.tsx b/components/landing/MedolUpdate.tsx index cafb9a0..bdec410 100644 --- a/components/landing/MedolUpdate.tsx +++ b/components/landing/MedolUpdate.tsx @@ -91,9 +91,31 @@ export default function MedolUpdate() { navigation={true} modules={[Navigation, Pagination]} spaceBetween={40} - slidesPerView={2} + slidesPerView={1} + breakpoints={{ + // When the window width is less than 640px + 720: { + slidesPerView: 2, // Set slidesPerView to 1 on mobile + }, + }} pagination={true} className="mySwiper" + onSwiper={(swiper) => { + swiper.navigation.nextEl?.classList.add( + "bg-white/70", + "!text-black", + "rounded-full", + "!w-[40px]", + "!h-[40px]" + ); + swiper.navigation.prevEl?.classList.add( + "bg-white/70", + "!text-black", + "rounded-full", + "!w-[40px]", + "!h-[40px]" + ); + }} > {mediahubUpdate?.map((newsItem: any) => ( @@ -108,7 +130,7 @@ export default function MedolUpdate() { radius="lg" width="300%" alt="tes" - className="object-cover h-[270px]" + className="object-cover !h-[30vh]" src={newsItem.thumbnailLink} /> @@ -141,9 +163,31 @@ export default function MedolUpdate() { navigation={true} modules={[Navigation, Pagination]} spaceBetween={40} - slidesPerView={2} + slidesPerView={1} + breakpoints={{ + // When the window width is less than 640px + 720: { + slidesPerView: 2, // Set slidesPerView to 1 on mobile + }, + }} pagination={true} className="mySwiper" + onSwiper={(swiper) => { + swiper.navigation.nextEl?.classList.add( + "bg-white/70", + "!text-black", + "rounded-full", + "!w-[40px]", + "!h-[40px]" + ); + swiper.navigation.prevEl?.classList.add( + "bg-white/70", + "!text-black", + "rounded-full", + "!w-[40px]", + "!h-[40px]" + ); + }} > {tbnUpdate?.map((newsItem: any) => ( @@ -158,7 +202,7 @@ export default function MedolUpdate() { radius="lg" width="300%" alt="tes" - className="object-cover h-[270px]" + className="object-cover !h-[30vh]" src={newsItem?.image} /> @@ -184,14 +228,36 @@ export default function MedolUpdate() {
- {/* + { + swiper.navigation.nextEl?.classList.add( + "bg-white/70", + "!text-black", + "rounded-full", + "!w-[40px]", + "!h-[40px]" + ); + swiper.navigation.prevEl?.classList.add( + "bg-white/70", + "!text-black", + "rounded-full", + "!w-[40px]", + "!h-[40px]" + ); + }} > {inpUpdate?.map((newsItem: any) => ( @@ -206,7 +272,7 @@ export default function MedolUpdate() { radius="lg" width="300%" alt="tes" - className="object-cover h-[270px]" + className="object-cover !h-[30vh]" src={newsItem.image} /> @@ -231,7 +297,7 @@ export default function MedolUpdate() {
- */} +
diff --git a/components/landing/NewsTicker.tsx b/components/landing/NewsTicker.tsx index 4771286..353ba7f 100644 --- a/components/landing/NewsTicker.tsx +++ b/components/landing/NewsTicker.tsx @@ -49,7 +49,7 @@ export default function NewsTicker() {
BREAKING NEWS -
+
{ + const cleaned = name.replace("Polda ", "").trim().toLowerCase(); + const slug = cleaned.replace(/\s+/g, "-"); + return slug; + }; + return (
@@ -312,7 +318,10 @@ export default function RegionalNews() {
*/}
{listPolda.map((item: any, index: any) => ( - +
{(onClose) => ( <> - -
+ +

{" "} {t("beritaWilayah")} @@ -367,14 +376,16 @@ export default function RegionalNews() { key={index.id} className="w-[140px] h-[115px] flex flex-col items-center justify-center rounded-lg shadow-sm" > - +

-

+

{item.title}

@@ -383,7 +394,11 @@ export default function RegionalNews() { ))} - diff --git a/components/landing/SidebarNav.tsx b/components/landing/SidebarNav.tsx index 4159c61..6db9e5e 100644 --- a/components/landing/SidebarNav.tsx +++ b/components/landing/SidebarNav.tsx @@ -30,7 +30,7 @@ export default function SidebarNav() { onClick={() => setSelectedTab("media")} className={ selectedTab === "media" - ? "text-black dark:text-white border-b-3 border-red-400 cursor-pointer py-2" + ? "text-black border-b-3 border-red-400 cursor-pointer py-2" : "text-slate-300 cursor-pointer py-2" } > @@ -40,7 +40,7 @@ export default function SidebarNav() { onClick={() => setSelectedTab("video")} className={ selectedTab === "video" - ? "text-black dark:text-white border-b-3 border-red-400 cursor-pointer py-2" + ? "text-black border-b-3 border-red-400 cursor-pointer py-2" : "text-slate-300 cursor-pointer py-2" } > @@ -91,10 +91,10 @@ export default function SidebarNav() { >
)} -

+ {/*

Pelayanan Informasi Publik

- + */} {/*
SERTIFIKAT ISO 9001:2015
@@ -163,7 +163,7 @@ export default function SidebarNav() {
*/} - {/*
+
Channel Humas Polri
-
*/} +
-

+ {/*

{" "} Info Eksternal

@@ -321,7 +321,7 @@ export default function SidebarNav() { Info dan Berita terbaru dari Komnas Perempuan Indonesia

-
+
*/} ); } diff --git a/components/layout/admin-layout.tsx b/components/layout/admin-layout.tsx index fe4f828..015ed1f 100644 --- a/components/layout/admin-layout.tsx +++ b/components/layout/admin-layout.tsx @@ -4,13 +4,14 @@ import { useEffect, useState } from "react"; import Sidebar from "./sidebar/sidebar"; import { SidebarProvider } from "./sidebar/sidebar-context"; import { Breadcrumb } from "../ui/breadcrumb"; +import SidebarMobile from "./sidebar/sidebar-mobile"; interface Props { children: React.ReactNode; } export const AdminLayout = ({ children }: Props) => { - const [isOpen, setIsOpen] = useState(true); + const [isOpen, setIsOpen] = useState(false); const updateSidebarData = (newData: boolean) => { setIsOpen(newData); }; @@ -29,6 +30,10 @@ export const AdminLayout = ({ children }: Props) => {
+
{children} diff --git a/components/layout/navbar/NavbarHumas.tsx b/components/layout/navbar/NavbarHumas.tsx index 4369e8c..8a8371c 100644 --- a/components/layout/navbar/NavbarHumas.tsx +++ b/components/layout/navbar/NavbarHumas.tsx @@ -68,15 +68,15 @@ export default function NavbarHumas(props: { size: string }) { const language = storedLanguage((state) => state.locale); const setLanguage = storedLanguage((state) => state.setLocale); - useEffect(() => { - if (!isAuthenticated) { - onLogout(); - } - }, [token]); + // useEffect(() => { + // if (!isAuthenticated) { + // onLogout(); + // } + // }, [token]); const onLogout = () => { Object.keys(Cookies.get()).forEach((cookieName) => { - Cookies.remove(cookieName); + Cookies.remove(cookieName, { path: "/" }); }); router.push("/auth"); }; @@ -154,7 +154,6 @@ export default function NavbarHumas(props: { size: string }) { logo - - + {" "} + + E-PPID + setIsOpen(state)} diff --git a/components/layout/sidebar/sidebar-mobile.tsx b/components/layout/sidebar/sidebar-mobile.tsx new file mode 100644 index 0000000..411bbe9 --- /dev/null +++ b/components/layout/sidebar/sidebar-mobile.tsx @@ -0,0 +1,481 @@ +import { SidebarMenuTask } from "@/types/globals"; +import { Tooltip } from "@nextui-org/react"; +import Link from "next/link"; +import { usePathname, useRouter } from "next/navigation"; +import React, { useEffect, useState } from "react"; +import { + ChevronLeftIcon, + ChevronRightIcon, + FormCustomIcon, + FormHorizontalIcon, + FormLayoutIcon, + FormValidationIcon, + FormVerticalIcon, +} from "../../icons"; +import { + ArticleIcon, + DashboardIcon, + HomeIcon, + InfoCircleIcon, + MagazineIcon, + MasterCategoryIcon, + MasterRoleIcon, + MasterUsersIcon, + MinusCircleIcon, + StaticPageIcon, + TableIcon, +} from "../../icons/sidebar-icon"; +import { ThemeSwitch } from "../../theme-switch"; +import { SidebarCollapseItems } from "./sidebar-collapse-items"; +import { SidebarCollapseSubItems } from "./sidebar-collapse-sub-items"; +import { useSidebar } from "./sidebar-context"; +import { SidebarMenu } from "./sidebar-menu"; +import Image from "next/image"; +import Cookies from "js-cookie"; +import { SettingsIcon, UserProfileIcon } from "@/components/icons/globals"; + +interface SubMenuItems { + id: number; + name: string; + modulePathUrl: string; + isSubActive: boolean; +} + +interface MenuItems { + id: number; + name: string; + modulePathUrl: string; + isSubActive: boolean; + childMenu?: SubMenuItems[]; + icon?: string; +} + +interface SidebarProps { + sidebarData: boolean; + updateSidebarData: (newData: boolean) => void; +} + +const sideBarDummyData = [ + { + id: 1, + name: "Dashboard", + moduleId: 652, + moduleName: "Dashboard", + modulePathUrl: "/admin/dashboard", + isGroup: true, + parentId: -1, + icon: "dashboard", + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 2, + name: "Dashboard", + moduleId: 652, + moduleName: "Dashboard", + modulePathUrl: "/admin/dashboard", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 3, + name: "Apps", + moduleId: 652, + moduleName: "Dashboard", + modulePathUrl: "/admin/basic", + isGroup: true, + parentId: -1, + icon: "table", + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 4, + name: "Artikel", + moduleId: 652, + moduleName: "Dashboard", + modulePathUrl: "/admin/article", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 30, + name: "Kategori", + moduleId: 654, + moduleName: "Master", + modulePathUrl: "/admin/master-category", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 4, + name: "Majalah", + moduleId: 652, + moduleName: "Apps", + modulePathUrl: "/admin/magazine", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + + // { + // id: 4, + // name: "E-Magazine", + // moduleId: 652, + // moduleName: "Dashboard", + // modulePathUrl: "/admin/e-magazine", + // parentId: -1, + // icon: , + // position: 1, + // statusId: 1, + // childMenu: [], + // statusName: "Active", + // childModule: null, + // }, + { + id: 5, + name: "Master", + moduleId: 652, + moduleName: "Dashboard", + isGroup: true, + modulePathUrl: "/admin/basic", + parentId: -1, + icon: "table", + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + // { + // id: 6, + // name: "Master Menu", + // moduleId: 652, + // moduleName: "Form Custom", + // modulePathUrl: "/admin/master-menu", + // parentId: -1, + // icon: , + // position: 1, + // statusId: 1, + // childMenu: [], + // statusName: "Active", + // childModule: null, + // }, + // { + // id: 7, + // name: "Master Module", + // moduleId: 653, + // moduleName: "Form Horizontal", + // modulePathUrl: "/admin/master-module", + // parentId: -1, + // icon: , + // position: 1, + // statusId: 1, + // childMenu: [], + // statusName: "Active", + // childModule: null, + // }, + { + id: 11, + name: "Master Static Page", + moduleId: 652, + moduleName: "Dashboard", + modulePathUrl: "/admin/static-page", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 8, + name: "Master User", + moduleId: 654, + moduleName: "Form Vertical", + modulePathUrl: "/admin/master-user", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + + { + id: 10, + name: "Master User Role", + moduleId: 656, + moduleName: "Form Validation", + modulePathUrl: "/admin/master-role", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, +]; + +const SidebarMobile: React.FC = ({ updateSidebarData }) => { + const pathname = usePathname(); + const router = useRouter(); + const [sidebarMenu, setSidebarMenu] = useState(); + const { isOpen, toggleSidebar } = useSidebar(); + const token = Cookies.get("access_token"); + const username = Cookies.get("username"); + const isAuthenticated = Cookies.get("is_authenticated"); + + useEffect(() => { + if (!token) { + onLogout(); + } + }, [token]); + + const onLogout = () => { + Object.keys(Cookies.get()).forEach((cookieName) => { + Cookies.remove(cookieName); + }); + router.push("/auth"); + }; + + useEffect(() => { + updateSidebarData(isOpen); + }, [isOpen]); + + return ( +
+
+
+ {!isOpen && ( +
+ +
+ )} +
+ + + {/* {isOpen && ACME} */} + + {isOpen && ( + + )} +
+ + + {sideBarDummyData + ? sideBarDummyData?.map((list: any, index: number) => + list.isGroup ? ( +

+ {isOpen ? list.name : "..."} +

+ ) : list.childMenu?.length < 1 ? ( + <> + {isOpen ? ( + + {/*
*/} +
+ {list.icon} {isOpen && list.name} +
+ + ) : ( + + +
+ {list.icon} {isOpen && list.name} +
+ +
+ )} + + ) : ( + ( + + )), + ]} + /> + ) + ) + : ""} + +
+
+
+
+ + {isOpen && "Theme"} +
+ {isOpen ? ( + +
+ {isOpen && "Settings"} +
+ + ) : ( + + +
+ {isOpen && "Settings"} +
+ +
+ )} + {isOpen ? ( + + ) : ( + + + + + + )} +
+
+
+
+ ); +}; + +export default SidebarMobile; diff --git a/components/layout/sidebar/sidebar.tsx b/components/layout/sidebar/sidebar.tsx index 763f9ed..2c88504 100644 --- a/components/layout/sidebar/sidebar.tsx +++ b/components/layout/sidebar/sidebar.tsx @@ -262,7 +262,7 @@ const Sidebar: React.FC = ({ updateSidebarData }) => { const onLogout = () => { Object.keys(Cookies.get()).forEach((cookieName) => { - Cookies.remove(cookieName); + Cookies.remove(cookieName, { path: "/" }); }); router.push("/auth"); }; diff --git a/components/main/dashboard/chart/column-chart.tsx b/components/main/dashboard/chart/column-chart.tsx index 4a300c4..9cfb30d 100644 --- a/components/main/dashboard/chart/column-chart.tsx +++ b/components/main/dashboard/chart/column-chart.tsx @@ -86,7 +86,6 @@ const ApexChartColumn = (props: { }) ); } else { - console.log("sadadad", getDatas.visit, getDatas.view, getDatas.share); setSeriesVisit(getDatas.visit); setSeriesView(getDatas.view); setSeriesShare(getDatas.share); diff --git a/components/main/dashboard/dashboard-container.tsx b/components/main/dashboard/dashboard-container.tsx index 9e95a7d..513908c 100644 --- a/components/main/dashboard/dashboard-container.tsx +++ b/components/main/dashboard/dashboard-container.tsx @@ -33,11 +33,86 @@ type ArticleData = Article & { createdAt: string; }; +interface TopPages { + id: number; + no: number; + title: string; + visits: number; +} + +interface PostCount { + id: number; + no: number; + name: string; + count: number; +} + +const dummyTopPages = [ + { id: 1, title: "Home Page", visits: 830 }, + { id: 2, title: "Media Update", visits: 762 }, + { id: 3, title: "Polda Metro Jaya", visits: 532 }, + { id: 4, title: "Kapolri: Transformasi Menuju Polri Presisi", visits: 500 }, + { id: 5, title: "Polda Jawa Barat Ungkap Kasus Narkoba", visits: 480 }, + { id: 6, title: "Polri Perketat Pengamanan Jelang Pemilu", visits: 460 }, + { id: 7, title: "Polda Jawa Tengah Berhasil Tangkap Buronan", visits: 440 }, + { + id: 8, + title: "Divisi Humas Polri Rilis Data Kejahatan Terbaru", + visits: 420, + }, + { id: 9, title: "Polda Sumatera Utara Gerebek Pabrik Narkoba", visits: 400 }, + { + id: 10, + title: "Kapolda Bali Imbau Wisatawan Waspada Kejahatan", + visits: 380, + }, +]; + +const dummyPostCount = [ + { id: 1, name: "Polda Sumatera Utara", count: 132 }, + { id: 2, name: "Polda Metro Jaya", count: 128 }, + { id: 3, name: "Polda Jawa Barat", count: 120 }, + { id: 4, name: "Polda Jawa Timur", count: 115 }, + { id: 5, name: "Polda Bali", count: 110 }, + { id: 6, name: "Polda Daerah Istimewa Yogyakarta", count: 105 }, + { id: 7, name: "Polda Riau", count: 98 }, + { id: 8, name: "Polda Sulawesi Selatan", count: 92 }, + { id: 9, name: "Polda Kalimantan Timur", count: 85 }, + { id: 10, name: "Polda Jawa Tengah", count: 78 }, + { id: 11, name: "Polda Kalimantan Selatan", count: 72 }, + { id: 12, name: "Polda Sumatera Barat", count: 65 }, + { id: 13, name: "Polda Papua", count: 60 }, + { id: 14, name: "Polda Nusa Tenggara Barat", count: 54 }, + { id: 15, name: "Polda Maluku", count: 49 }, + { id: 16, name: "Polda Bengkulu", count: 43 }, + { id: 17, name: "Polda Lampung", count: 37 }, + { id: 18, name: "Polda Sulawesi Tenggara", count: 30 }, + { id: 19, name: "Polda Gorontalo", count: 24 }, + { id: 20, name: "Polda Kalimantan Barat", count: 18 }, + { id: 21, name: "Polda Kepulauan Riau", count: 10 }, + { id: 22, name: "Polda Sulawesi Barat", count: 8 }, + { id: 23, name: "Polda Papua Barat", count: 5 }, + { id: 24, name: "Polda Maluku Utara", count: 3 }, + { id: 25, name: "Polda Nusa Tenggara Timur", count: 2 }, + { id: 26, name: "Polda Kalimantan Tengah", count: 1 }, + { id: 27, name: "Polda Sulawesi Tengah", count: 1 }, + { id: 28, name: "Polda Bangka Belitung", count: 1 }, + { id: 29, name: "Polda Jambi", count: 0 }, + { id: 30, name: "Polda Banten", count: 0 }, + { id: 31, name: "Polda Aceh", count: 0 }, + { id: 32, name: "Polda Kalimantan Utara", count: 0 }, + { id: 33, name: "Polda Sulawesi Utara", count: 0 }, + { id: 34, name: "Polda Kepulauan Bangka Belitung", count: 0 }, + { id: 35, name: "Polda Sumatera Selatan", count: 0 }, +]; + export default function DashboardContainer() { const username = Cookies.get("username"); const fullname = Cookies.get("ufne"); const [page, setPage] = useState(1); const [totalPage, setTotalPage] = useState(1); + const [topPagespage, setTopPagesPage] = useState(1); + const [topPagesTotalPage, setTopPagesTotalPage] = useState(1); const [article, setArticle] = useState([]); const [analyticsView, setAnalyticView] = useState([ "visit", @@ -49,10 +124,20 @@ export default function DashboardContainer() { endDate: new Date(), }); + const [postContentDate, setPostContentDate] = useState({ + startDate: new Date(new Date().setDate(new Date().getDate() - 7)), + endDate: new Date(), + }); + const [typeDate, setTypeDate] = useState("monthly"); + const [topPages, setTopPages] = useState([]); + const [postCount, setPostCount] = useState([]); + useEffect(() => { initState(); + fetchTopPages(); + fetchPostCount(); }, [page]); async function initState() { @@ -66,6 +151,28 @@ export default function DashboardContainer() { setTotalPage(res?.data?.meta?.totalPage); } + async function fetchTopPages() { + setTopPages(getTableNumber(10, dummyTopPages)); + setTopPagesTotalPage(1); + } + async function fetchPostCount() { + setPostCount(getTableNumber(10, dummyPostCount)); + setTopPagesTotalPage(1); + } + + const getTableNumber = (limit: number, data: any) => { + if (data) { + const startIndex = limit * (page - 1); + let iterate = 0; + const newData = data.map((value: any) => { + iterate++; + value.no = startIndex + iterate; + return value; + }); + return newData; + } + }; + const getMonthYear = (date: Date | string) => { const newDate = new Date(date); @@ -90,10 +197,10 @@ export default function DashboardContainer() { }; return ( -
+
-
-
+
+

{fullname}

@@ -111,28 +218,28 @@ export default function DashboardContainer() {
-
+
Total post
121
-
+
Total views
154
-
+
Total share
154
-
+
@@ -140,69 +247,51 @@ export default function DashboardContainer() {
530
-
-
-
-
- Analytics -
- - - Visit - - - View - - - Share - - -
-
-
- - -
- setStartDateValue(e)} - inputClassName="z-50 w-full text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-xl h-[40px] text-gray-600 dark:text-gray-300" - /> -
-
-
-
-
- +
+
+

+ Rekapitulasi Post Berita Polda Pada Website +

+
+ setPostContentDate(e)} + inputClassName="z-50 w-full text-xs lg:text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-sm lg:rounded-lg h-[30px] lg:h-[40px] text-gray-600 dark:text-gray-300" />
+
+
NO
+
POLDA
+
+ JUMLAH POST BERITA +
+
+
+ {postCount?.map((list) => ( +
+
{list?.no}
+
{list?.name}
+
+ {list?.count} +
+
+ ))} +
-
-
+
+

Recent Article

+
+
+
+
+ Analytics +
+ + + Visit + + + View + + + Share + + + + + Visit + + + View + + + Share + + +
+
+
+ + +
+ setStartDateValue(e)} + inputClassName="z-50 w-full text-xs lg:text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-sm lg:rounded-lg h-[30px] lg:h-[40px] text-gray-600 dark:text-gray-300" + /> +
+
+
+
+
+ +
+
+
+
+
+

Top Pages

+
+
+
No
+
Title
+
Visits
+
+ {topPages?.map((list) => ( +
+
{list?.no}
+
{list?.title}
+
{list?.visits}
+
+ ))} +
+ setTopPagesPage(page)} + /> +
+
+
); diff --git a/components/main/detail/comment.tsx b/components/main/detail/comment.tsx index fff98b7..581a1ff 100644 --- a/components/main/detail/comment.tsx +++ b/components/main/detail/comment.tsx @@ -1,11 +1,30 @@ import { Button } from "@nextui-org/button"; import { Input, Textarea } from "@nextui-org/input"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import * as z from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; -import { otpRequest, otpValidation } from "@/service/master-user"; +import { + deleteArticleComment, + editArticleComment, + getArticleComment, + otpRequest, + otpValidation, + postArticleComment, +} from "@/service/master-user"; import { error } from "@/config/swal"; +import { UserProfileIcon } from "@/components/icons/globals"; +import { convertDateFormat } from "@/utils/global"; +import Cookies from "js-cookie"; +import OTPInput from "react-otp-input"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { SendIcon, TimesIcon } from "@/components/icons"; +import { saveActivity } from "@/service/activity-log"; +import { usePathname } from "next/navigation"; + +const userId = Cookies.get("uie"); +const token = Cookies.get("access_token"); const commentSchema = z.object({ name: z.string().min(1, { @@ -24,9 +43,17 @@ const commentSchema = z.object({ }), }); -export default function Comment() { +export default function Comment(props: { id: string | null }) { + const { id } = props; + const MySwal = withReactContent(Swal); + const pathname = usePathname(); const [needOtp, setNeedOtp] = useState(false); const [otpValue, setOtpValue] = useState(""); + const [commentList, setCommentList] = useState([]); + const [openCommentId, setOpenCommentId] = useState(0); + const [editCommentId, setEditCommentId] = useState(0); + const [replyValue, setReplyValue] = useState(""); + const [editValue, setEditValue] = useState(""); const formOptions = { resolver: zodResolver(commentSchema), }; @@ -36,11 +63,21 @@ export default function Comment() { handleSubmit, formState: { errors }, setValue, + reset, } = useForm(formOptions); + useEffect(() => { + fetchData(); + }, [id]); + + const fetchData = async () => { + const res = await getArticleComment(String(id)); + setCommentList(res?.data?.data); + }; + const onSubmit = async (values: z.infer) => { if (!needOtp) { - const res = await otpRequest(values.email); + const res = await otpRequest(values.email, values?.name); if (res?.error) { error(res.message); return false; @@ -52,139 +89,420 @@ export default function Comment() { error("OTP Tidak Sesuai"); return false; } - const req = { - email: values.email, - name: values.name, - comment: values.comment, + + const data = { + articleId: Number(id), + isPublic: true, + message: values.comment, + parentId: 0, }; - console.log("req", req); + const res = await postArticleComment(data); + if (res?.error) { + error(res?.message); + return false; + } + const req: any = { + activityTypeId: 5, + url: "https://kontenhumas.com/" + pathname, + articleId: Number(id), + }; + + const resActivity = await saveActivity(req); + reset(); + fetchData(); + setNeedOtp(false); } }; + + const handleDelete = async (id: number) => { + MySwal.fire({ + title: "Delete Comment", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + doDelete(id); + } + }); + }; + + const doDelete = async (id: number) => { + const res = await deleteArticleComment(id); + if (res?.error) { + error(res?.message); + return false; + } + MySwal.fire({ + title: "Sukses", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + } + }); + fetchData(); + }; + + const sendComment = async (idComment: number) => { + const data = { + articleId: Number(id), + isPublic: true, + message: replyValue, + parentId: idComment, + }; + + const res = await postArticleComment(data); + if (res?.error) { + error(res?.message); + return false; + } + const req: any = { + activityTypeId: 5, + url: "https://kontenhumas.com/" + pathname, + articleId: Number(id), + userId: Number(userId), + }; + + const resActivity = await saveActivity(req, token); + + fetchData(); + }; + + // const sendActivity = async () => {}; + const editComment = async (idComment: number, parentId: number) => { + const data = { + articleId: Number(id), + isPublic: true, + id: idComment, + message: editValue, + parentId: parentId, + }; + + const res = await editArticleComment(data, idComment); + if (res?.error) { + error(res?.message); + return false; + } + setEditCommentId(0); + fetchData(); + }; + + const childComment = (parentId: number) => { + const filteredComment = commentList.filter( + (a: any) => a.parentId === parentId + ); + + return filteredComment.length > 0 ? ( +
+ {filteredComment.map((list: any) => ( +
+ +
+
+

{list?.commentFromName}

+

{convertDateFormat(list?.updatedAt)}

+
+ {editCommentId === list?.id ? ( + + } + labelPlacement="outside" + className="w-full " + classNames={{ + inputWrapper: [ + "border-1 rounded-lg", + "dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400", + ], + }} + variant="bordered" + /> + setEditCommentId(0)} + > + + +
+ ) : ( +
+

{list?.message}

+ +
+ {userId === "16" && ( + { + setEditValue(list?.message); + setEditCommentId(list?.id); + }} + > + Edit + + )} + {(userId === String(list?.commentFromId) || + userId === "16") && ( + handleDelete(list?.id)} + > + Hapus + + )} +
+
+ )} +
+
+ ))} +
+ ) : ( + "" + ); + }; + return ( -
- Tinggalkan balasan -

- Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai{" "} - * -

-
-

Komentar

- ( -