diff --git a/app/(admin)/admin/(basic-form)/form-costum/page.tsx b/app/(admin)/admin/(basic-form)/form-costum/page.tsx new file mode 100644 index 0000000..224d54c --- /dev/null +++ b/app/(admin)/admin/(basic-form)/form-costum/page.tsx @@ -0,0 +1,30 @@ +"use client" +import { Image } from "@nextui-org/react"; + +export default function CustumPage() { + return ( +
+
+
+
+ +
+
+

Custum Form

+

custom designed elemnt

+
+
+ NextUI hero Image +
+
+
+
+ {/* */} +
+
+ ); +} diff --git a/app/(admin)/admin/(basic-form)/form-horizontal/page.tsx b/app/(admin)/admin/(basic-form)/form-horizontal/page.tsx new file mode 100644 index 0000000..63b5dc8 --- /dev/null +++ b/app/(admin)/admin/(basic-form)/form-horizontal/page.tsx @@ -0,0 +1,38 @@ +"use client" +import CreateCustomForm from "@/components/form/form-costum/custom-form"; +import CreateHorizontalForm from "@/components/form/form-horizontal/custom-form"; +import CreateWizardForm from "@/components/form/form-wizard/wizard-form"; +import AuthtorsTable from "@/components/table/authors-table"; +import CustomerTable from "@/components/table/customers-table"; +import InvoiceTable from "@/components/table/invoice-table"; +import UserTable from "@/components/table/article-table"; +import UsersTable from "@/components/table/users-table"; +import { Card, Divider, Image } from "@nextui-org/react"; + +export default function HorizontalPage() { + return ( +
+
+
+
+ +
+
+

Horizontal Form

+

Home{" > "} Horizontal Form

+
+
+ NextUI hero Image +
+
+
+
+ +
+
+ ); +} diff --git a/app/(admin)/admin/(basic-form)/form-layout/page.tsx b/app/(admin)/admin/(basic-form)/form-layout/page.tsx new file mode 100644 index 0000000..74c70ca --- /dev/null +++ b/app/(admin)/admin/(basic-form)/form-layout/page.tsx @@ -0,0 +1,40 @@ +"use client" + +import CreateLayoutForm from "@/components/form/form-layout/layout-form"; +import CreateValidationForm from "@/components/form/form-validation/validation-form"; +import CreateWizardForm from "@/components/form/form-wizard/wizard-form"; +import AuthtorsTable from "@/components/table/authors-table"; +import CustomerTable from "@/components/table/customers-table"; +import InvoiceTable from "@/components/table/invoice-table"; +import UserTable from "@/components/table/article-table"; +import UsersTable from "@/components/table/users-table"; +import { Card, Divider, Image } from "@nextui-org/react"; +import { useEffect, useState } from "react"; + +export default function FormLayoutPage() { + + return ( +
+
+
+
+
+
+

Form Layout

+

Home{" > "} Form Layout

+
+
+ NextUI hero Image +
+
+
+
+ +
+
+ ); +} diff --git a/app/(admin)/admin/(basic-form)/form-validation/page.tsx b/app/(admin)/admin/(basic-form)/form-validation/page.tsx new file mode 100644 index 0000000..8480b7e --- /dev/null +++ b/app/(admin)/admin/(basic-form)/form-validation/page.tsx @@ -0,0 +1,37 @@ +"use client" +import CreateValidationForm from "@/components/form/form-validation/validation-form"; +import CreateWizardForm from "@/components/form/form-wizard/wizard-form"; +import AuthtorsTable from "@/components/table/authors-table"; +import CustomerTable from "@/components/table/customers-table"; +import InvoiceTable from "@/components/table/invoice-table"; +import UserTable from "@/components/table/article-table"; +import UsersTable from "@/components/table/users-table"; +import { Card, Divider, Image } from "@nextui-org/react"; + +export default function ValidationPage() { + return ( +
+
+
+
+ +
+
+

Form Validation

+

Home{" > "} Form Validation

+
+
+ NextUI hero Image +
+
+
+
+ +
+
+ ); +} diff --git a/app/(admin)/admin/(basic-form)/form-vertical/page.tsx b/app/(admin)/admin/(basic-form)/form-vertical/page.tsx new file mode 100644 index 0000000..1667561 --- /dev/null +++ b/app/(admin)/admin/(basic-form)/form-vertical/page.tsx @@ -0,0 +1,32 @@ +"use client" +import CreateValidationForm from "@/components/form/form-validation/validation-form"; +import CreateVerticalForm from "@/components/form/form-vertical/vertical-form"; +import { Card, Divider, Image } from "@nextui-org/react"; + +export default function VerticalPage() { + return ( +
+
+
+
+ +
+
+

Vertical Form

+

Home{" > "} Verical Form

+
+
+ NextUI hero Image +
+
+
+
+ +
+
+ ); +} diff --git a/app/(admin)/admin/(basic-form)/form-wizard/page.tsx b/app/(admin)/admin/(basic-form)/form-wizard/page.tsx new file mode 100644 index 0000000..b096f16 --- /dev/null +++ b/app/(admin)/admin/(basic-form)/form-wizard/page.tsx @@ -0,0 +1,44 @@ +"use client" +import CreateWizardForm from "@/components/form/form-wizard/wizard-form"; +import AuthtorsTable from "@/components/table/authors-table"; +import CustomerTable from "@/components/table/customers-table"; +import InvoiceTable from "@/components/table/invoice-table"; +import UserTable from "@/components/table/article-table"; +import UsersTable from "@/components/table/users-table"; +import { Card, Divider, Image } from "@nextui-org/react"; + +export default function WizardPage() { + return ( +
+
+
+
+ +
+
+

Form Wizard

+

This is Form WizardPage

+
+
+ NextUI hero Image +
+
+
+
+ +

Form Wizard

+ +
+ +
+ + +
+
+
+ ); +} diff --git a/app/(admin)/admin/article/create/page.tsx b/app/(admin)/admin/article/create/page.tsx new file mode 100644 index 0000000..e0230bd --- /dev/null +++ b/app/(admin)/admin/article/create/page.tsx @@ -0,0 +1,10 @@ +import FormArticle from '@/components/form/form-article' +import { Card } from '@nextui-org/react' + +export default function CreateArticle() { + return ( + + + + ) +} diff --git a/app/(admin)/admin/article/page.tsx b/app/(admin)/admin/article/page.tsx new file mode 100644 index 0000000..f71a4fd --- /dev/null +++ b/app/(admin)/admin/article/page.tsx @@ -0,0 +1,24 @@ +"use client" +import { AddIcon } from "@/components/icons"; +import ArticleTable from "@/components/table/article-table"; +import { Button, Card } from "@nextui-org/react"; +import Link from "next/link"; + +export default function BasicPage() { + return ( +
+
+ + + + + + + + +
+
+ ); +} diff --git a/app/(admin)/admin/basic/page.tsx b/app/(admin)/admin/basic/page.tsx new file mode 100644 index 0000000..f9d5058 --- /dev/null +++ b/app/(admin)/admin/basic/page.tsx @@ -0,0 +1,39 @@ +"use client" +import { Card, Divider, Image } from "@nextui-org/react"; + +export default function BasicPage() { + return ( +
+
+
+
+
+
+

Basic Table

+

Home{" > "} Basic Table

+
+
+ NextUI hero Image +
+
+
+
+ +

Basic Table

+ +
+ {/* + + + + */} +
+
+
+
+ ); +} diff --git a/app/(admin)/admin/dashboard/page.tsx b/app/(admin)/admin/dashboard/page.tsx new file mode 100644 index 0000000..7f3d529 --- /dev/null +++ b/app/(admin)/admin/dashboard/page.tsx @@ -0,0 +1,11 @@ +import DashboardContainer from "@/components/main/dashboard/dashboard-container"; + +export default function AdminPage() { + return ( +
+
+ +
+
+ ) +} \ No newline at end of file diff --git a/app/(admin)/admin/layout.tsx b/app/(admin)/admin/layout.tsx new file mode 100644 index 0000000..4205ed4 --- /dev/null +++ b/app/(admin)/admin/layout.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { AdminLayout } from "@/components/layout/admin-layout"; + +export default function AdminPageLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/app/(admin)/admin/menu1/submenu1/page.tsx b/app/(admin)/admin/menu1/submenu1/page.tsx new file mode 100644 index 0000000..e87ac7f --- /dev/null +++ b/app/(admin)/admin/menu1/submenu1/page.tsx @@ -0,0 +1,8 @@ +import { ThemeSwitch } from "@/components/theme-switch"; + +export default function Submenu1Page() { + return ( +
Submenu1 +
+ ) +} \ No newline at end of file diff --git a/app/(admin)/admin/menu1/submenu2/page.tsx b/app/(admin)/admin/menu1/submenu2/page.tsx new file mode 100644 index 0000000..648391b --- /dev/null +++ b/app/(admin)/admin/menu1/submenu2/page.tsx @@ -0,0 +1,8 @@ +import { ThemeSwitch } from "@/components/theme-switch"; + +export default function Submenu2Page() { + return ( +
Submenu2 +
+ ) +} \ No newline at end of file diff --git a/app/(admin)/admin/page.tsx b/app/(admin)/admin/page.tsx new file mode 100644 index 0000000..5d41348 --- /dev/null +++ b/app/(admin)/admin/page.tsx @@ -0,0 +1,11 @@ +"use client" + +export default function HomePage() { + return ( +
+
+

Welcome

+
+
+ ); +} diff --git a/app/admin/dashboard/page.tsx b/app/(admin)/dashboard-old/page.tsx similarity index 100% rename from app/admin/dashboard/page.tsx rename to app/(admin)/dashboard-old/page.tsx diff --git a/app/admin/layout.tsx b/app/admin/layout.tsx deleted file mode 100644 index 1909d3a..0000000 --- a/app/admin/layout.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import HumasAdminLayout from "@/components/layout/HumasAdminLayout"; - -export default function HumasLayoutAdmin({ - children, -}: { - children: React.ReactNode; -}) { - return ( - - {children} - - ); -} diff --git a/app/layout.tsx b/app/layout.tsx index 9872d6a..d2581cc 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -37,7 +37,7 @@ export default function RootLayout({ )} > -
+
{children}
diff --git a/components/Landing Page/BodyLayout.tsx b/components/Landing Page/BodyLayout.tsx index aac639b..d83ff16 100644 --- a/components/Landing Page/BodyLayout.tsx +++ b/components/Landing Page/BodyLayout.tsx @@ -2,6 +2,7 @@ import CategorySatker from './CategorySatker' import ENewsPolri from './ENewsPolri' import MediaSocial from './MediaSocial' +import MedolUpdate from './MedolUpdate' import RegionalNews from './RegionalNews' import SidebarNav from './SidebarNav' @@ -10,6 +11,7 @@ export default function BodyLayout() { <>
+ diff --git a/components/Landing Page/Footer.tsx b/components/Landing Page/Footer.tsx index 65e8801..e4fdf2c 100644 --- a/components/Landing Page/Footer.tsx +++ b/components/Landing Page/Footer.tsx @@ -5,11 +5,10 @@ import { MailIcon } from '../icons' export default function Footer() { return (
-
- - +
+
-
+

Berita Terkini

Info Komnas Anak

@@ -46,13 +45,13 @@ export default function Footer() {

Pelayanan Polisiku

Pelayanan BINMAS

-
+

Subscribe

Dapatkan info & event terupdate dari kami.

} @@ -62,10 +61,10 @@ export default function Footer() {
} /> - +
-
© Copyright Humas

  POLRI ®

  All Rights Reserved
+
© Copyright Humas

  POLRI ®

  All Rights Reserved
) } diff --git a/components/Landing Page/HeaderNews.tsx b/components/Landing Page/HeaderNews.tsx index 4a38a67..896becc 100644 --- a/components/Landing Page/HeaderNews.tsx +++ b/components/Landing Page/HeaderNews.tsx @@ -8,8 +8,20 @@ import 'swiper/css/pagination'; import { Autoplay, Pagination, Navigation } from 'swiper/modules'; import Link from 'next/link'; import GPRKominfo from '../SocialMedia/GprKominfo'; +import { useEffect, useState } from 'react'; +import { getListArticle } from '@/service/article'; export default function HeaderNews() { + const [article, setArticle] = useState(); + + useEffect(() => { + async function getArticle() { + const response = await getListArticle(); + console.log("res", response?.data?.data); + } + getArticle(); + }, []); + const newsData = [ { id: 1, diff --git a/components/Landing Page/MediaSocial.tsx b/components/Landing Page/MediaSocial.tsx index 2381a67..d7441b6 100644 --- a/components/Landing Page/MediaSocial.tsx +++ b/components/Landing Page/MediaSocial.tsx @@ -1,14 +1,8 @@ -import { useEffect, useState } from 'react'; -import { ChevronRightIcon, DotsIcon, FbIcon, IgIcon, TtIcon, TwitterIcon, YtIcon } from '../icons'; -import { ScrollShadow } from '@nextui-org/react'; -import { Tweet } from 'react-tweet'; import Link from 'next/link'; -import YoutubePages from '../SocialMedia/Youtube'; -import YoutubeWidget from '../SocialMedia/Youtube'; -import InstagramWidget from '../SocialMedia/Instagram'; -import TiktokWidget from '../SocialMedia/Tiktok'; import Facebookwidget from '../SocialMedia/Facebook'; +import InstagramWidget from '../SocialMedia/Instagram'; import TwitterWidget from '../SocialMedia/Twitter'; +import { ChevronRightIcon, FbIcon, IgIcon, TtIcon, TwitterIcon, YtIcon } from '../icons'; export default function MediaSocial() { // const [limitedData, setLimitedData] = useState([]); diff --git a/components/Landing Page/MedolUpdate.tsx b/components/Landing Page/MedolUpdate.tsx new file mode 100644 index 0000000..af27a03 --- /dev/null +++ b/components/Landing Page/MedolUpdate.tsx @@ -0,0 +1,246 @@ +import { Button, Card, CardBody, CardFooter, Image, Tab, Tabs } from '@nextui-org/react'; +import React from 'react' +import { Swiper, SwiperSlide } from 'swiper/react'; +import 'swiper/css'; +import 'swiper/css/navigation'; +import 'swiper/css/pagination'; +import { Navigation, Pagination } from 'swiper/modules'; + +export default function MedolUpdate() { + + const mediaHubUpdate = [ + { + id: 1, + image: '/temp/mediahub1.png', + title: 'Peringatan Nuzulul Quran, Kapolda Sulbar Harap Kegiatan Ini Tambah Wawasan dan', + createdDate: '12 Januari 2024', + time: '13:00 WITA' + }, + { + id: 2, + image: '/temp/mediahub2.png', + title: 'Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak', + createdDate: '14 Januari 2024', + time: '13:00 WIB' + }, + { + id: 3, + image: '/temp/mediahub2.png', + title: 'Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak', + createdDate: '14 Januari 2024', + time: '13:00 WIB' + }, + { + id: 4, + image: '/temp/mediahub2.png', + title: 'Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak', + createdDate: '14 Januari 2024', + time: '13:00 WIB' + }, + { + id: 5, + image: '/temp/mediahub2.png', + title: 'Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak', + createdDate: '14 Januari 2024', + time: '13:00 WIB' + }, + ] + + return ( +
+
+ Top 5 News Update +
+
+ + + + {mediaHubUpdate.map((newsItem) => ( + + + + tes + + +

02-04-2024 09:31 WITA

+ Peringatan Nuzulul Quran, Kapolda Sulbar Harap Kegiatan Ini Tambah Wawasan dan +
+
+
+ ))} +
+
+ +
+
+ +
+ console.log("item pressed")} className='w-[45%] bg-white text-black'> + + tes + + +

02-04-2024 09:31 WITA

+ Peringatan Nuzulul Quran, Kapolda Sulbar Harap Kegiatan Ini Tambah Wawasan dan +
+
+ console.log("item pressed")} className='w-[45%] bg-white text-black'> + + tes + + +

02-04-2024 09:16 WIB

+ Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak +
+
+
+
+ +
+
+ +
+ console.log("item pressed")} className='w-[45%] bg-white text-black'> + + tes + + +

02-04-2024 09:31 WITA

+ Peringatan Nuzulul Quran, Kapolda Sulbar Harap Kegiatan Ini Tambah Wawasan dan +
+
+ console.log("item pressed")} className='w-[45%] bg-white text-black'> + + tes + + +

02-04-2024 09:16 WIB

+ Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak +
+
+
+
+ +
+
+ +
+ console.log("item pressed")} className='w-[45%] bg-white text-black'> + + tes + + +

02-04-2024 09:31 WITA

+ Peringatan Nuzulul Quran, Kapolda Sulbar Harap Kegiatan Ini Tambah Wawasan dan +
+
+ console.log("item pressed")} className='w-[45%] bg-white text-black'> + + tes + + +

02-04-2024 09:16 WIB

+ Kapolri Tinjau Langsung Kondisi Pelayanan Pemudik di Dermaga 1 Pelabuhan Merak +
+
+
+
+ +
+
+
+
+
+ ) +} diff --git a/components/Landing Page/RegionalNews.tsx b/components/Landing Page/RegionalNews.tsx index d8dd656..0a6f6cb 100644 --- a/components/Landing Page/RegionalNews.tsx +++ b/components/Landing Page/RegionalNews.tsx @@ -47,13 +47,13 @@ export default function RegionalNews() { const listPoldaAll = [ { id: 1, - img: "/assets/polda/polda-metro.svg", + img: "/assets/polda/polda-metro-jaya.svg", title: "Polda Metro Jaya", path: '/news/polda-metro-jaya' }, { id: 2, - img: "/assets/polda/polda-jabar.svg", + img: "/assets/polda/polda-jawa-barat.svg", title: "Polda Jawa Barat", path: '/news/polda-jawa-barat' }, @@ -209,7 +209,7 @@ export default function RegionalNews() { }, { id: 28, - img: "/assets/polda/polda-sulut.svg", + img: "/assets/polda/polda-sulawesi-utara.svg", title: "Polda Sulawesi Utara", path: '/news/polda-sulawesi-utara' }, diff --git a/components/Landing Page/SidebarNav.tsx b/components/Landing Page/SidebarNav.tsx index 1bc8d60..413c0b8 100644 --- a/components/Landing Page/SidebarNav.tsx +++ b/components/Landing Page/SidebarNav.tsx @@ -1,4 +1,4 @@ -import { LinkIcon, ScrollShadow } from '@nextui-org/react' +import { Button, LinkIcon, ScrollShadow } from '@nextui-org/react' import React from 'react' import { EyeIcon } from '../icons' import Image from 'next/image' @@ -8,11 +8,22 @@ export default function SidebarNav() { return ( <>
+
+ SERTIFIKAT ISO 9001:2015 +
+
+ publikasi +
Media Update
-
- +
+ +
+

Pelihara Kondusifitas Kamtibmas, Personel Polsek Sayan Sambangi Warganya yang Masih Beraktifitas Pada Malam Hari

+

21-07-2023 13:50

+

82

+

Pelihara Kondusifitas Kamtibmas, Personel Polsek Sayan Sambangi Warganya yang Masih Beraktifitas Pada Malam Hari

21-07-2023 13:50

@@ -34,8 +45,15 @@ export default function SidebarNav() {

82

+
-
Publikasi +
+ Publikasi
publikasi publikasi @@ -55,6 +73,9 @@ export default function SidebarNav() {
Channel Humas Polri
+ + humas-polri + humas-polri @@ -64,9 +85,12 @@ export default function SidebarNav() { humas-polri - + humas-polri + + humas-polri +
diff --git a/components/detail/Propim.tsx b/components/detail/Propim.tsx index 40a8aa7..ef375f0 100644 --- a/components/detail/Propim.tsx +++ b/components/detail/Propim.tsx @@ -1,6 +1,5 @@ 'use client' -import { Card, CardBody, Tab, Tabs } from '@nextui-org/react' -import React from 'react' +import { Tab, Tabs } from '@nextui-org/react' export default function Task() { return ( diff --git a/components/form/form-article.tsx b/components/form/form-article.tsx new file mode 100644 index 0000000..55e99a0 --- /dev/null +++ b/components/form/form-article.tsx @@ -0,0 +1,264 @@ +'use client' +import { Button, Card, Chip, Input, Select, SelectItem, Selection } from '@nextui-org/react' +import JoditEditor from 'jodit-react'; +import React, { useRef, useState } from 'react' +import * as z from "zod"; +import Swal from 'sweetalert2'; +import withReactContent from 'sweetalert2-react-content'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { createArticle } from '@/service/article'; +import { error } from '@/config/swal'; + +const articleSchema = z.object({ + title: z.string().min(1, { message: "Required" }), + article: z.string().min(1, { message: "Required" }), + slug: z.string().min(1, { message: "Required" }), + tags: z.string().min(0, { message: "Required" }).optional(), + description: z.string().min(1, { message: "Required" }).optional(), + +}); + +export default function FormArticle() { + const [id, setId] = useState(); + const [title, setTitle] = useState(""); + const [article, setArticle] = React.useState(new Set([])); + const [slug, setSlug] = useState(""); + const [tags, setTags] = useState([]); + const [newTags, setNewTags] = useState(""); + const editor = useRef(null); + const [content, setContent] = useState(''); + const MySwal = withReactContent(Swal); + + const formOptions = { resolver: zodResolver(articleSchema) }; + type MicroIssueSchema = z.infer; + const { + register, + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm(formOptions); + + const TypeId = [ + { + key: 1, + label: "Article" + }, + { + key: 2, + label: "Magazine" + }, + ] + + const CategoryArticle = [ + { + key: 1, + label: "Article" + }, + { + key: 2, + label: "Magazine" + }, + ] + + const handleClose = (tagsToRemove: string) => { + setTags(tags.filter((tag) => tag !== tagsToRemove)); + if (tags.length === 1) { + setTags([]); + } + }; + + const handleAddTags = (e: any) => { + if (newTags.trim() !== "") { + setTags([...tags, newTags.trim()]); + setNewTags(""); + e.preventDefault(); + } + }; + + const handleKeyDown = (event: any) => { + if (event.key === "Enter") { + handleAddTags(event); + } + }; + + + async function save(data: any,) { + const formData = { + id: id, + title, + jenisArtikel: article, + slug, + tags, + description: content, + }; + + console.log("Form Data:", formData); + if (id != undefined) { + formData.id = id; + } + + const response = await createArticle(formData); + + if (response?.error) { + error(response.message); + return false; + } + }; + + async function onSubmit(data: any) { + MySwal.fire({ + title: "Simpan Data", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + } + return ( +
+
+ +
+ setTitle(e.target.value)} + label="Judul" + variant='bordered' + placeholder="Enter Text" + labelPlacement='outside' + /> +
+ {(title.length === 0 && errors.title) && errors.title.message} + +
+
+
+ +
+ {errors.article?.message} +
+ {/*

{article}

*/} +
+
+ setSlug(e.target.value)} + label="Slug" + variant='bordered' + placeholder="Enter Text" + labelPlacement='outside' + /> +
+ {(slug.length === 0 && errors.slug) && errors.slug.message} +
+
+
+ setNewTags(e.target.value)} + onKeyDown={handleKeyDown} + placeholder="Tambahkan tag baru dan tekan Enter" + /> +
+ {(tags.length === 0 && errors.tags) && errors.tags.message} +
+
+ {tags.map((tag, index) => ( + handleClose(tag)}> + {tag} + + ))} +
+
+
+

Description

+ setContent(newContent)} + className="dark:text-black" + + /> +
+ {(content.length === 0 && errors.description) && errors.description.message} +
+
+
+

Attachment (Opsional)

+
+ +
+
+ +
+
+
+ ) +} diff --git a/components/icons.tsx b/components/icons.tsx index 68f120f..a417d7c 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -772,28 +772,140 @@ export const Checklist = ({ ); -export const AddIcon = ({ +export const ChevronLeftIcon = ({ size, - height = 12, - width = 12, - fill = "none", + height = 24, + width = 24, + fill = "currentColor", ...props }: IconSvgProps) => ( + + +); + +export const DotsYIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + +); + + +export const DotsXIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + +); + +export const EyeIconMdi = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + ); + +export const OnlineIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + +); + +export const OfflineIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + +); + export const CreateIconIon = ({ size, height = 24, @@ -841,11 +953,54 @@ export const DeleteIcon = ({ ); -export const DotsYIcon = ({ + +export const AccIcon = ({ size, - height = 24, - width = 24, - fill = "currentColor", + height = 12, + width = 10, + fill = "none", + ...props +}: IconSvgProps) => ( + + + + +); + +export const CloseIcon = ({ + size, + height = 12, + width = 10, + fill = "none", + ...props +}: IconSvgProps) => ( + + + + +); + +export const RefundIcon = ({ + size, + height = 12, + width = 10, + fill = "none", ...props }: IconSvgProps) => ( + fill="currentColor" + d="m4 8l-.707.707L2.586 8l.707-.707zm5 12a1 1 0 1 1 0-2zm-.707-6.293l-5-5l1.414-1.414l5 5zm-5-6.414l5-5l1.414 1.414l-5 5zM4 7h10.5v2H4zm10.5 13H9v-2h5.5zm6.5-6.5a6.5 6.5 0 0 1-6.5 6.5v-2a4.5 4.5 0 0 0 4.5-4.5zM14.5 7a6.5 6.5 0 0 1 6.5 6.5h-2A4.5 4.5 0 0 0 14.5 9z"> + + + +); + +export const AddIcon = ({ + size, + height = 12, + width = 12, + fill = "none", + ...props +}: IconSvgProps) => ( + + + +); + +export const CompanyIcon = ({ + size, + height = 12, + width = 12, + fill = "none", + ...props +}: IconSvgProps) => ( + + ); -export const EyeIconMdi = ({ +export const EmailIcon = ({ + size, + height = 12, + width = 12, + fill = "none", + ...props +}: IconSvgProps) => ( + + + + + +); + +export const PhoneIcon = ({ + size, + height = 12, + width = 12, + fill = "none", + ...props +}: IconSvgProps) => ( + + + + +); + +export const MessageIcon = ({ + size, + height = 12, + width = 12, + fill = "none", + ...props +}: IconSvgProps) => ( + + + + + +); + + +export const UserIcon = ({ + size, + height = 12, + width = 12, + fill = "none", + ...props +}: IconSvgProps) => ( + + + + + + +); + +export const EyeOffIconMdi = ({ size, height = 24, width = 24, @@ -881,12 +1165,38 @@ export const EyeIconMdi = ({ > ); -export const TimesIcon = ({ +export const DateIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + +); + +export const WarningIcon = ({ size, height = 24, width = 24, @@ -898,10 +1208,272 @@ export const TimesIcon = ({ height={size || height} width={size || width} viewBox="0 0 24 24" - fill={fill} {...props} > - + + + + +); + +export const PasswordIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + +); + +export const TimeIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + +); + +export const VolumeLowIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + +); + +export const VolumeHighIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + +); + +export const FormVerticalIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + ); +export const FormHorizontalIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const FormCustomIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const FormLayoutIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const FormValidationIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const FormWizardIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const FacebookIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + +); + +export const GoogleIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + + + + + +); diff --git a/components/icons/dashboard-icon.tsx b/components/icons/dashboard-icon.tsx new file mode 100644 index 0000000..0ba10c7 --- /dev/null +++ b/components/icons/dashboard-icon.tsx @@ -0,0 +1,172 @@ +import * as React from "react"; +import { IconSvgProps } from "@/types/globals"; + + +export const DashboardUserIcon = ({ + size, + height = 48, + width = 48, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const DashboardBriefcaseIcon = ({ + size, + height = 48, + width = 48, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + +); +export const DashboardMailboxIcon = ({ + size, + height = 48, + width = 48, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + +); +export const DashboardBookmarkIcon = ({ + size, + height = 48, + width = 48, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + + + +); +export const DashboardSpeecIcon = ({ + size, + height = 48, + width = 48, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + +); + +export const DashboardConnectIcon = ({ + size, + height = 48, + width = 48, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + + +); + + +export const DashboardTopLeftPointIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + + +export const DashboardRightDownPointIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + +); \ No newline at end of file diff --git a/components/icons/sidebar-icon.tsx b/components/icons/sidebar-icon.tsx new file mode 100644 index 0000000..691ca2c --- /dev/null +++ b/components/icons/sidebar-icon.tsx @@ -0,0 +1,167 @@ +import * as React from "react"; +import { IconSvgProps } from "@/types/globals"; + +export const MenuBurgerIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const DashboardIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const HomeIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + +); + +export const Submenu1Icon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + + + + +); + +export const Submenu2Icon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); + +export const InfoCircleIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + +); + + +export const MinusCircleIcon = ({ + size, + height = 24, + width = 24, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + + + + + + +); + +export const TableIcon = ({ + size, + height = 24, + width = 22, + fill = "currentColor", + ...props +}: IconSvgProps) => ( + + + +); \ No newline at end of file diff --git a/components/layout/admin-layout.tsx b/components/layout/admin-layout.tsx new file mode 100644 index 0000000..2b4e2c4 --- /dev/null +++ b/components/layout/admin-layout.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { useEffect, useState } from "react"; +import Sidebar from "../sidebar/sidebar"; +import { SidebarProvider } from "../sidebar/sidebar-context"; +import { Breadcrumb } from "../ui/breadcrumb"; + +interface Props { + children: React.ReactNode; +} + +export const AdminLayout = ({ children }: Props) => { + const [isOpen, setIsOpen] = useState(true); + const updateSidebarData = (newData: boolean) => { + setIsOpen(newData); + }; + + const [hasMounted, setHasMounted] = useState(false); + + // Hooks + useEffect(() => { + setHasMounted(true); + }, []); + + // Render + if (!hasMounted) return null; + + return ( + +
+ +
+ + {children} +
+
+
+ ); +}; \ No newline at end of file diff --git a/components/main/dashboard/chart/column-chart.tsx b/components/main/dashboard/chart/column-chart.tsx new file mode 100644 index 0000000..e1a9181 --- /dev/null +++ b/components/main/dashboard/chart/column-chart.tsx @@ -0,0 +1,81 @@ +import React, { Component } from 'react'; +import ReactApexChart from 'react-apexcharts'; + +interface State { + series: { name: string; data: number[] }[]; + options: { + chart: { type: string; height: number }; + plotOptions: { bar: { colors: { ranges: { from: number; to: number; color: string }[] }; columnWidth: string } }; + dataLabels: { enabled: boolean }; + yaxis: { title: { text: string }; labels: { formatter: (y: number) => string } }; + xaxis: { type: string; categories: string[]; labels: { rotate: number } }; + }; +} + +class ApexChartColumn extends Component<{}, State> { + render() { + return ( +
+
+ { + return y.toFixed(0); + }, + }, + }, + xaxis: { + type: 'datetime', + categories: [ + '2020-05-01', '2020-05-02', '2020-05-03', '2020-05-04', '2020-05-05', + ], + labels: { + rotate: -90, + }, + }, + + }} + series={[ + { + name: 'Earning This Month ', + data: [ + 1.45, 5.9, -0.42, -12.6, -18.1 + ], + }, + ]} type="bar" height={350} /> +
+
+
+ ); + } +} + +export default ApexChartColumn; \ No newline at end of file diff --git a/components/main/dashboard/chart/donut-chart.tsx b/components/main/dashboard/chart/donut-chart.tsx new file mode 100644 index 0000000..921c099 --- /dev/null +++ b/components/main/dashboard/chart/donut-chart.tsx @@ -0,0 +1,51 @@ +import React, { Component } from 'react'; +import ReactApexChart from 'react-apexcharts'; + +interface State { + series: { name: string; data: number[] }[]; + options: { + chart: { type: string; height: number }; + dataLabels: { enabled: boolean }; + }; +} + +class ApexChartDonut extends Component<{}, State> { + render() { + return ( +
+
+ +
+
+
+ ); + } +} + +export default ApexChartDonut; \ No newline at end of file diff --git a/components/main/dashboard/chart/line-area-chart.tsx b/components/main/dashboard/chart/line-area-chart.tsx new file mode 100644 index 0000000..7ea3ed9 --- /dev/null +++ b/components/main/dashboard/chart/line-area-chart.tsx @@ -0,0 +1,74 @@ +import React, { Component } from 'react'; +import ReactApexChart from 'react-apexcharts'; + +interface State { + series: { name: string; data: number[] }[]; + options: { + chart: { type: string; height: number }; + plotOptions: { bar: { colors: { ranges: { from: number; to: number; color: string }[] }; columnWidth: string } }; + dataLabels: { enabled: boolean }; + yaxis: { title: { text: string }; labels: { formatter: (y: number) => string } }; + xaxis: { type: string; categories: string[]; labels: { rotate: number } }; + }; +} + +class ApexChartLineArea extends Component<{}, State> { + render() { + return ( +
+ +
+ ); + } +} + +export default ApexChartLineArea; \ No newline at end of file diff --git a/components/main/dashboard/dashboard-container.tsx b/components/main/dashboard/dashboard-container.tsx new file mode 100644 index 0000000..0d09829 --- /dev/null +++ b/components/main/dashboard/dashboard-container.tsx @@ -0,0 +1,176 @@ +'use client' +import { DashboardBookmarkIcon, DashboardBriefcaseIcon, DashboardConnectIcon, DashboardMailboxIcon, DashboardRightDownPointIcon, DashboardSpeecIcon, DashboardTopLeftPointIcon, DashboardUserIcon } from "@/components/icons/dashboard-icon"; +import { Submenu1Icon } from "@/components/icons/sidebar-icon"; +import { Button, Select, SelectItem, SelectSection } from "@nextui-org/react"; +import ApexChartColumn from "./chart/column-chart"; +import ApexChartDonut from "./chart/donut-chart"; +import ApexChartLineArea from "./chart/line-area-chart"; + +export default function DashboardContainer() { + return ( +
+
+
+
+
+
Employees
+
96
+
+
+
+
Clients
+
3650
+
+
+
+
Projects
+
356
+
+
+
+
Events
+
696
+
+
+
+
Payroll
+
$96k
+
+
+
+
Reports
+
56
+
+
+
+
+
+
Revenue Update + Overview of Profit +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+

$63,489.50

+

Total Earnings

+
+
+
+
+
+

Earning this month

+

$48,820

+
+
+
+
+
+

Expense this month

+

$26,498

+
+
+ +
+
+
+
+
+
+

Yearly Breakup

+
+

$36,358

+
+
+

+9% last year

+
+

+

+
+ 2020 +
+
+
+ 2020 +
+

+ +
+
+
+
+
+
+ Monthly Earning + $ +
+
+

$6,820

+
+
+ +
+

-6% last year

+
+
+
+
+
+
+
bawah
+
+
+ ) +} \ No newline at end of file diff --git a/components/navbar/NavbarHumas.tsx b/components/navbar/NavbarHumas.tsx index a4e5cc5..c6e7fc3 100644 --- a/components/navbar/NavbarHumas.tsx +++ b/components/navbar/NavbarHumas.tsx @@ -1,20 +1,39 @@ 'use client' +import { siteConfig } from '@/config/site'; import { Input } from '@nextui-org/input'; import { Navbar, NavbarContent, NavbarItem, NavbarMenu, NavbarMenuItem, NavbarMenuToggle } from '@nextui-org/navbar'; -import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownSection, DropdownTrigger, autocomplete } from '@nextui-org/react'; -import Link from "next/link"; -import { ChevronDownIcon, ChevronRightIcon, ChevronRightWhite, ChevronUpIcon, FbIcon, IdnIcon, IgIcon, SearchIcon, TtIcon, TwIcon, YtIcon } from '../icons'; -import { ThemeSwitch } from '../theme-switch'; +import { Button, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger } from '@nextui-org/react'; import Image from 'next/image'; -import { siteConfig } from '@/config/site'; +import Link from "next/link"; import { useState } from 'react'; +import { ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, FbIcon, IdnIcon, IgIcon, SearchIcon, TtIcon, TwIcon, YtIcon } from '../icons'; +import { ThemeSwitch } from '../theme-switch'; + +interface MenuItem { + key: string; + label: string; + href: URL; + submenu?: SubMenuItem[]; +} + +interface SubMenuItem { + label: string; + href: string; +} + +interface DropdownOpenState { + [key: string]: boolean; +} + export default function NavbarHumas() { + const [dropdownOpen, setDropdownOpen] = useState({}); - const [dropdownOpen, setDropdownOpen] = useState(false); - - const toggleDropdown = () => { - setDropdownOpen(!dropdownOpen); + const toggleDropdown = (key: any) => { + setDropdownOpen({ + ...dropdownOpen, + [key]: !dropdownOpen[key] + }); }; const searchInput = ( @@ -138,7 +157,7 @@ export default function NavbarHumas() {
-
Portal PPID
+
Portal PPID
@@ -249,34 +268,38 @@ export default function NavbarHumas() { {/* {searchInput} */}
- {siteConfig.humasMenuItems.map((item, index) => ( - - {item.submenu ? ( -
- - {dropdownOpen && ( -
- {item.submenu.map((subItem, subIndex) => ( - - {subItem.label} - - ))} -
+ ) )}
- ) : ( - - {item.label} - +
+ {dropdownOpen[item.key] && item.submenu && ( +
+ {item.submenu.map((subItem, subIndex) => ( +
+ + {subItem.label} + +
+ ))} +
)} - +
))}
diff --git a/components/sidebar/sidebar-closed-icon.tsx b/components/sidebar/sidebar-closed-icon.tsx new file mode 100644 index 0000000..b6aa291 --- /dev/null +++ b/components/sidebar/sidebar-closed-icon.tsx @@ -0,0 +1,36 @@ +import Link from "next/link"; +import { DashboardIcon, HomeIcon, TableIcon } from "../icons/sidebar-icon"; +import { useSidebar } from "./sidebar-context"; +import { Tooltip } from "@nextui-org/react"; + +export default function ClosedSidebarIcon(props: { icon: string, isActive: boolean, childMenu: any, path: string, title: string }) { + const { isOpen, toggleSidebar } = useSidebar(); + + const { icon, isActive, childMenu, path, title } = props; + const renderIcon = () => { + switch (icon) { + case 'dashboard': + return ; + case 'menu1': + return ; + case 'table': + return ; + default: + return null; // Tidak ada ikon yang sesuai + } + }; + return ( + + {childMenu.length < 1 ? + < Link href={path} className={`w-fit rounded-lg p-1 flex items-center ${isActive ? "bg-[#11181c] dark:bg-white text-[#fafafa] dark:text-black" : "text-zinc-600 dark:text-zinc-400 hover:text-zinc-800 hover:dark:text-zinc-300"}`}> + {renderIcon()} + + + : + + {renderIcon()} + + } + + ) +} \ No newline at end of file diff --git a/components/sidebar/sidebar-collapse-items.tsx b/components/sidebar/sidebar-collapse-items.tsx new file mode 100644 index 0000000..1d2fd93 --- /dev/null +++ b/components/sidebar/sidebar-collapse-items.tsx @@ -0,0 +1,73 @@ +import React, { useEffect, useState } from "react"; +import clsx from "clsx"; +import { Accordion, AccordionItem, Tooltip } from "@nextui-org/react"; + +import { ChevronUpIcon } from "../icons"; +import { DashboardIcon, HomeIcon, TableIcon } from "../icons/sidebar-icon"; +import { useSidebar } from "./sidebar-context"; + +interface Props { + icon?: string; + title: string; + items?: React.ReactNode[]; + isActive: boolean; +} + +export const SidebarCollapseItems = ({ + title, + items, + icon, + isActive, +}: Props) => { + + const { isOpen, toggleSidebar } = useSidebar(); + + // useEffect(() => { + // console.log("Sidebar Collapse Item :: ", title, isActive); + // }, []); + + const renderIcon = () => { + switch (icon) { + case 'dashboard': + return ; + case 'menu1': + return ; + case 'table': + return ; + default: + return null; // Tidak ada ikon yang sesuai + } + }; + return ( +
+ + } + classNames={{ + // indicator: "data-[open=true]:-rotate-180", + indicator: `${isOpen ? "data-[open=true]:-rotate-180" : "hidden"}`, + trigger: `${isOpen ? "pl-[7px]" : "pl-[11px] "} py-2 rounded-lg active:scale-[0.98] transition-transform text-center ${isActive ? "bg-zinc-600 dark:bg-zinc-300 text-zinc-300 dark:text-zinc-500 font-bold font-bold hover:font-bold" : " hover:bg-zinc-400 hover:font-semibold"}`, + title: `${isOpen ? "pl-2 gap-2" : "px-0"} flex text-base h-full items-center cursor-pointer`, + }} + aria-label="Accordion 1" + title={ +
+ {icon && {icon}} + {/* {isOpen && {title}} */} + {isOpen && {title}} +
+ + } + > +
+
    {items}
+
+
+
+
+ ); +}; diff --git a/components/sidebar/sidebar-collapse-sub-items.tsx b/components/sidebar/sidebar-collapse-sub-items.tsx new file mode 100644 index 0000000..a9ba224 --- /dev/null +++ b/components/sidebar/sidebar-collapse-sub-items.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from "react"; +import { Accordion, AccordionItem, Tooltip } from "@nextui-org/react"; +import clsx from "clsx"; +import Link from "next/link"; +import { ChevronUpIcon } from "../icons"; +import { Submenu1Icon, Submenu2Icon } from "../icons/sidebar-icon"; +import { useSidebar } from "./sidebar-context"; + +interface SubSubItems { + title: string; + path: string; + isSubActive: boolean; +} + +interface SubItems { + title: string; + path: string; + isActive: boolean; + isSubActive: boolean; + subItems?: SubSubItems[]; +} + +interface Props { + title: string; + icon?: any; + path: string; + isActive: boolean; + isParentActive: boolean; +} + +export const SidebarCollapseSubItems = ({ + title, + icon, + path, + isActive, + isParentActive, +}: Props) => { + const [open, setOpen] = useState(false); + let no = 0; + + // useEffect(() => { + // console.log("Sidebar Collapse Sub Item :: ", title, path, isParentActive, isActive, icon); + // }, []); + + const { isOpen, toggleSidebar } = useSidebar(); + + const renderIcon = () => { + switch (icon) { + case 'submenu1': + return ; + case 'submenu2': + return ; + default: + return null; // Tidak ada ikon yang sesuai + } + }; + return ( +
  • + + {isOpen ? + +
    + {icon} {isOpen && title} +
    + + : + + +
    + {icon} {isOpen && title} +
    + +
    + + } + +
  • + ); +}; diff --git a/components/sidebar/sidebar-context.tsx b/components/sidebar/sidebar-context.tsx new file mode 100644 index 0000000..a566005 --- /dev/null +++ b/components/sidebar/sidebar-context.tsx @@ -0,0 +1,58 @@ +'use client' +import React, { createContext, useContext, useEffect, useState } from 'react'; + +interface SidebarContextType { + isOpen: boolean; + toggleSidebar: () => void; +} + +const SidebarContext = createContext(undefined); + +export const SidebarProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [isOpen, setIsOpen] = useState(() => { + if (typeof window !== 'undefined') { + const storedValue = localStorage.getItem('sidebarOpen'); + return storedValue ? JSON.parse(storedValue) : false; + } + }); + + const toggleSidebar = () => { + setIsOpen(!isOpen); + }; + + useEffect(() => { + localStorage.setItem('sidebarOpen', JSON.stringify(isOpen)); + }, [isOpen]); + + useEffect(() => { + const handleResize = () => { + setIsOpen(window.innerWidth > 768); // Ganti 768 dengan lebar yang sesuai dengan breakpoint Anda + }; + + handleResize(); // Pastikan untuk memanggil fungsi handleResize saat komponen dimuat + + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + + return ( + + {children} + + ); +}; + +export const useSidebar = () => { + const context = useContext(SidebarContext); + if (!context) { + throw new Error('useSidebar must be used within a SidebarProvider'); + } + return context; +}; + +export const useSidebarContext = () => { + return useContext(SidebarContext); +}; \ No newline at end of file diff --git a/components/sidebar/sidebar-menu.tsx b/components/sidebar/sidebar-menu.tsx new file mode 100644 index 0000000..b98128e --- /dev/null +++ b/components/sidebar/sidebar-menu.tsx @@ -0,0 +1,15 @@ +import React from "react"; + +interface Props { + title?: string; + children?: React.ReactNode; +} + +export const SidebarMenu = ({ title, children }: Props) => { + return ( +
    + {title} + {children} +
    + ); +}; diff --git a/components/sidebar/sidebar.tsx b/components/sidebar/sidebar.tsx new file mode 100644 index 0000000..d3f5974 --- /dev/null +++ b/components/sidebar/sidebar.tsx @@ -0,0 +1,474 @@ +import { SidebarMenuTask } from "@/types/globals"; +import { Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, Tooltip, User } from '@nextui-org/react'; +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import React, { useEffect, useState } from 'react'; +import { ChevronLeftIcon, ChevronRightIcon, FormCustomIcon, FormHorizontalIcon, FormLayoutIcon, FormValidationIcon, FormVerticalIcon } from '../icons'; +import { DashboardIcon, HomeIcon, InfoCircleIcon, MinusCircleIcon, 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"; + +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: 4, + name: "E-Magazine", + moduleId: 652, + moduleName: "Dashboard", + modulePathUrl: "/admin/pagination-basic", + 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/form-costum", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 7, + name: "Master Module", + moduleId: 653, + moduleName: "Form Horizontal", + modulePathUrl: "/admin/form-horizontal", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 8, + name: "Master User", + moduleId: 654, + moduleName: "Form Vertical", + modulePathUrl: "/admin/form-vertical", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + { + id: 9, + name: "Master User Levels", + moduleId: 655, + moduleName: "Form Layout", + modulePathUrl: "/admin/form-layout", + 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/form-validation", + parentId: -1, + icon: , + position: 1, + statusId: 1, + childMenu: [], + statusName: "Active", + childModule: null, + }, + // { + // id: 11, + // name: "Form Wizard", + // moduleId: 657, + // moduleName: "Form Wizard", + // modulePathUrl: "/admin/form-wizard", + // parentId: -1, + // icon: , + // position: 1, + // statusId: 1, + // childMenu: [], + // statusName: "Active", + // childModule: null, + // }, + // { + // id: 13, + // name: "Others", + // moduleId: 658, + // moduleName: "Others", + // modulePathUrl: "/admin/basic", + // isGroup: true, + // parentId: -1, + // icon: "table", + // position: 1, + // statusId: 1, + // childMenu: [], + // statusName: "Active", + // childModule: null, + // }, + // { + // id: 13, + // name: "Menu 1", + // moduleId: 652, + // moduleName: "Menu 1", + // modulePathUrl: "/admin/menu1", + // parentId: -1, + // icon: , + // position: 1, + // statusId: 1, + // statusName: "Active", + // childMenu: [ + // { + // id: 3, + // name: "SubMenu 1", + // moduleId: 653, + // moduleName: "SubMenu 1", + // modulePathUrl: "/admin/menu1/submenu1", + // parentId: 702, + // icon: , + // position: 2, + // statusId: 1, + // statusName: "Active", + // childMenu: [], + // childModule: null, + // }, + // { + // id: 4, + // name: "SubMenu 2", + // moduleId: 653, + // moduleName: "SubMenu 2", + // modulePathUrl: "/admin/menu1/submenu2", + // parentId: 702, + // icon: , + // position: 2, + // statusId: 1, + // statusName: "Active", + // childMenu: [], + // childModule: null, + // } + // ], + // childModule: null, + // }, +] + +const Sidebar: React.FC = ({ updateSidebarData }) => { + const pathname = usePathname(); + const [sidebarMenu, setSidebarMenu] = useState(); + const { isOpen, toggleSidebar } = useSidebar(); + + const closeSidebar = () => { + if (isOpen) { + toggleSidebar(); + } + }; + + useEffect(() => { + updateSidebarData(isOpen) + }, [isOpen]) + + const renderIcon = (icon: string) => { + switch (icon) { + case 'dashboard': + return ; + case 'menu1': + return ; + case 'table': + return ; + default: + return null; + } + }; + + return ( +
    +
    + + {!isOpen && +
    + +
    + } +
    +
    + + {isOpen && ACME} +
    + {isOpen && + + } +
    +
    +
    + + + + + + +

    Signed in as

    +

    @tonyreichert

    +
    + Profile Settings + + Analytics + + + Help & Feedback + + + Log Out + +
    +
    +
    +
    + + {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 && "Support"} + + : + + + + {isOpen && "Support"} + + + } + {isOpen ? + + + {isOpen && "Log Out"} + + : + + + + {isOpen && "Log Out"} + + + + } + +
    +
    +
    + + {/*
    +
    + +
    + {sideBarDummyData.map((list) => ( +
    + +
    + ))} + +
    + {isOpen && ( +
    + )} */} +
    + ); +}; + +export default Sidebar; \ No newline at end of file diff --git a/components/table/article-table.tsx b/components/table/article-table.tsx new file mode 100644 index 0000000..7248b24 --- /dev/null +++ b/components/table/article-table.tsx @@ -0,0 +1,253 @@ +"use client"; +import { + AddIcon, + CreateIconIon, + DeleteIcon, + DotsYIcon, + EyeFilledIcon, + EyeIcon, + EyeIconMdi +} from "@/components/icons"; +import { getListArticle } from "@/service/article"; +import { Article } from "@/types/globals"; +import { Button } from "@nextui-org/button"; +import { + Chip, + ChipProps, + Dropdown, + DropdownItem, + DropdownMenu, + DropdownTrigger, + Spinner, + Table, + TableBody, + TableCell, + TableColumn, + TableHeader, + TableRow, + User +} from "@nextui-org/react"; +import Link from "next/link"; +import { Key, useCallback, useEffect, useState } from "react"; + +type UserObject = { + id: number; + user: string; + status: string; + projectName: string; + avatar: string; +}; + +const statusColorMap = { + active: "success", + paused: "danger", + vacation: "warning", +}; + + +export default function ArticleTable() { + const [article, setArticle] = useState([]); + + useEffect(() => { + async function initState() { + const res = await getListArticle(); + setArticle(res.data?.data); + + console.log("Data Aritcle", res.data.data); + } + + initState(); + + }, []); + type TableRow = (typeof usersTable)[0]; + + const columns = [ + + { name: "No", uid: "no" }, + { name: "Judul", uid: "title" }, + { name: "Kategori", uid: "articleCategory" }, + { name: "Tanggal Unggah", uid: "createdDate" }, + { name: "Kreator", uid: "creator" }, + { name: "Sumber", uid: "source" }, + // { name: "Users", uid: "users" }, + { name: "Status", uid: "status" }, + { name: "Aksi", uid: "actions" }, + ]; + + // const statusOptions = [ + // { name: "Active", uid: "active" }, + // { name: "Paused", uid: "paused" }, + // { name: "Vacation", uid: "vacation" }, + // ]; + + const usersTable = [ + { + id: 1, + user: "Olivia Rhya", + status: "active", + projectName: "Xtreme admin", + avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU", + }, + { + id: 2, + user: "Barbara Steele", + status: "cancel", + projectName: "Adminpro admin", + avatar: "https://cdn.icon-icons.com/icons2/2859/PNG/512/avatar_face_man_boy_male_profile_smiley_happy_people_icon_181661.png", + }, + { + id: 3, + user: "Leonardo Gordon", + status: "pending", + projectName: "Monster admin", + avatar: "https://cdn.icon-icons.com/icons2/2859/PNG/512/avatar_face_man_boy_male_profile_smiley_happy_people_icon_181657.png", + }, + { + id: 4, + user: "Evelyn Pope", + status: "cancel", + projectName: "Materialpro admin", + avatar: "https://cdn.icon-icons.com/icons2/3708/PNG/512/man_person_people_avatar_icon_230017.png", + }, + { + id: 5, + user: "Tommy Garza", + status: "cancel", + projectName: "Elegant admin", + avatar: "https://cdn.icon-icons.com/icons2/1736/PNG/512/4043275-avatar-man-person-punk_113271.png", + }, + + + ]; + + const renderCell = useCallback( + (article: Article, columnKey: Key) => { + const cellValue = article[columnKey as keyof Article]; + const statusColorMap: Record = { + active: "primary", + cancel: "danger", + pending: "success", + }; + + switch (columnKey) { + case "no": + return ( +
    {article.id}
    + ) + + case "status": + return ( + +
    + {cellValue} +
    +
    + ); + + case "actions": + return ( +
    + + + + + + + + + + Detail + + + + + + + + Edit + + + + + + + + Delete + + + + + + +
    + ); + + default: + return cellValue; + } + }, []); + + return ( + <> + +
    +
    + + + {(column) => ( + {column.name} + )} + + } + > + {(item) => ( + + {(columnKey) => ( + {renderCell(item, columnKey)} + )} + + )} + +
    +
    +
    + + + ); +} diff --git a/components/table/users-table.tsx b/components/table/users-table.tsx new file mode 100644 index 0000000..fd1055c --- /dev/null +++ b/components/table/users-table.tsx @@ -0,0 +1,207 @@ +"use client"; +import { + TableCell, + TableRow, + Table, + TableHeader, + TableColumn, + TableBody, + Pagination, + Dropdown, + DropdownTrigger, + DropdownMenu, + DropdownItem, + Input, + User, + Card, + Divider, + Chip, + ChipProps, +} from "@nextui-org/react"; +import { Button } from "@nextui-org/button"; +import React, { Key, useCallback, useMemo, useState } from "react"; +import { + AccIcon, + CloseIcon, + CreateIconIon, + DeleteIcon, + DotsXIcon, + DotsYIcon, + EyeIconMdi, + OfflineIcon, + OnlineIcon, + RefundIcon, + SearchIcon, +} from "@/components/icons"; +import Link from "next/link"; + +type UserObject = { + id: number; + user: string; + status: string; + projectName: string; + avatar: string; + +}; + +export default function UsersTable() { + type TableRow = (typeof usersTable)[0]; + + const columns = [ + + { name: "Users", uid: "user" }, + { name: "ProjectName", uid: "projectName" }, + { name: "Team", uid: "team" }, + { name: "Status", uid: "status" }, + { name: "Budget", uid: "budget" }, + ]; + + + const usersTable = [ + { + id: 1, + user: "Sunil Joshi", + description: "Web Designer", + team: "S", + status: "Active", + projectName: "Elite admin", + budget: "$3.9k", + avatar: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSa8Luglga9J2R3Bxt_PsWZISUHQWODD6_ZTAJ5mIQgxYCAE-YbkY81faTqp-hSA_jVPTs&usqp=CAU", + }, + { + id: 2, + user: "AndrewMcDownland", + description: "Project Manager", + team: "T", + status: "Pending", + projectName: "Real Homes WP Theme", + budget: "$24.5k", + avatar: "https://cdn.icon-icons.com/icons2/2859/PNG/512/avatar_face_man_boy_male_profile_smiley_happy_people_icon_181661.png", + }, + { + id: 3, + user: "Cristopher jamil", + description: "Project Manager", + team: "X", + status: "Completed", + projectName: "MediacalPro WP Theme", + budget: "$12.8k", + avatar: "https://cdn.icon-icons.com/icons2/2859/PNG/512/avatar_face_man_boy_male_profile_smiley_happy_people_icon_181657.png", + }, + { + id: 4, + user: "Nirav Joshi", + description: "Frontend Engineer", + team: "A", + status: "Active", + projectName: "Hosting Press HTML", + budget: "$2.4k", + avatar: "https://cdn.icon-icons.com/icons2/3708/PNG/512/man_person_people_avatar_icon_230017.png", + }, + { + id: 5, + user: "MichealDoe", + description: "Content Writer", + team: "S", + status: "Cancel", + projectName: "Helping Hands WP Theme", + budget: "$9.3k", + avatar: "https://cdn.icon-icons.com/icons2/1736/PNG/512/4043275-avatar-man-person-punk_113271.png", + }, + + + ]; + + const renderCell = useCallback((basic: TableRow, columnKey: Key) => { + const cellValue = basic[columnKey as keyof UserObject]; + const statusColorMap: Record = { + Active: "success", + Cancel: "danger", + Pending: "warning", + Completed: "primary" + }; + + switch (columnKey) { + case "no": + return ( +
    {basic.id}
    + ) + + case "user": + return ( + + {basic.description} + + ) + + case "team": + return ( +
    {cellValue}
    + ) + + case "status": + return ( + +
    + {cellValue} +
    +
    + ); + + case "budget": + return ( +
    +

    {cellValue}

    +
    + ); + + default: + return cellValue; + } + }, []); + + return ( + <> + +
    +
    + + + {(column) => ( + {column.name} + )} + + + {(item) => ( + + {(columnKey) => ( + {renderCell(item, columnKey)} + )} + + )} + +
    +
    +
    + + + ); +} diff --git a/components/ui/breadcrumb.tsx b/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..b277ff9 --- /dev/null +++ b/components/ui/breadcrumb.tsx @@ -0,0 +1,55 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { Button } from "@nextui-org/button"; +import { BreadcrumbItem, Breadcrumbs } from "@nextui-org/react"; +import { usePathname, useRouter } from "next/navigation"; +import { Image } from "@nextui-org/react"; +import { FormLayoutIcon } from "../icons"; + +export const Breadcrumb = () => { + const [currentPage, setCurrentPage] = useState(""); + const router = useRouter(); + const pathname = usePathname(); + const pathnameSplit = pathname.split("/"); + pathnameSplit.shift(); + let pathnameTransformed = pathnameSplit.map(item => { + let words = item.split('-'); + let capitalizedWords = words.map(word => word.charAt(0).toUpperCase() + word.slice(1)); + return capitalizedWords.join(' '); + }); + + console.log('pathname : ', pathnameTransformed); + + useEffect(() =>{ + setCurrentPage(pathnameSplit[pathnameSplit.length - 1]) + }, [pathnameSplit]) + + const handleAction = (key: any) => { + const keyIndex = pathnameSplit.indexOf(key); + const combinedPath = pathnameSplit.slice(0, keyIndex + 1).join('/'); + router.push("/" + combinedPath); + } + + return ( +
    +
    +
    +
    +

    {pathnameTransformed[pathnameTransformed.length - 1]}

    + handleAction(key)}> + {pathnameTransformed?.map((item, index) => ( + + {item} + + ))} + +
    +
    + +
    +
    +
    +
    + ); +}; diff --git a/config/site.ts b/config/site.ts index 5fa9b1b..d52edc5 100644 --- a/config/site.ts +++ b/config/site.ts @@ -41,7 +41,7 @@ export const siteConfig = { }, { label: "Profile Pimpinan POLRI", - href: "/visi-misi" + href: "/profile-pimpinan-polri" }, { label: "Struktur Organisasi", @@ -76,43 +76,43 @@ export const siteConfig = { }, { label: "Pelayanan SIM", - href: "/visi-misi" + href: "https://www.digitalkorlantas.id/sim/" }, { label: "Pelayanan e-Rikkes SIM", - href: "/struktur-organisasi" + href: "https://erikkes.id/" }, { label: "Pelayanan Tes Psikologi SIM", - href: "/visi-misi" + href: "https://eppsi.id/" }, { label: "Pelayanan e-Avis", - href: "/tugas-dan-fungsi" + href: "https://e-avis.korlantas.polri.go.id/" }, { label: "Pelayanan Samsat Digital", - href: "#" + href: "https://samsatdigital.id/" }, { label: "Pelayanan SKCK", - href: "#" + href: "https://play.google.com/store/apps/details?id=superapps.polri.presisi.presisi&hl=en_US" }, { label: "Pelayanan Propam Presisi", - href: "#" + href: "https://play.google.com/store/apps/details?id=com.stk.pengaduanpropam" }, { label: "Pelayanan Dumas Presisi", - href: "#" + href: "https://dumaspresisi.polri.go.id/" }, { label: "Pelayanan Binmas", - href: "#" + href: "https://bos.polri.go.id/login" }, { label: "Wistle Blower System", - href: "#" + href: "https://play.google.com/store/apps/details?id=id.go.ssdmpolri.pengaduanappsbarupolri2" }, ] }, diff --git a/config/swal.ts b/config/swal.ts index d27ce92..642044b 100644 --- a/config/swal.ts +++ b/config/swal.ts @@ -24,7 +24,7 @@ export function loading(msg?: any) { timerProgressBar: true, didOpen: () => { MySwal.showLoading(); - timerInterval = setInterval(() => {}, 100); + timerInterval = setInterval(() => { }, 100); }, willClose: () => { clearInterval(timerInterval); diff --git a/package-lock.json b/package-lock.json index 6bf829c..8362cad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "@types/react": "18.2.21", "@types/react-datepicker": "^6.0.1", "@types/react-dom": "18.2.7", + "apexcharts": "^3.48.0", "autoprefixer": "10.4.16", "axios": "^1.6.8", "clsx": "^2.0.0", @@ -41,12 +42,15 @@ "next-themes": "^0.2.1", "postcss": "8.4.31", "react": "18.2.0", + "react-apexcharts": "^1.4.1", "react-datepicker": "^6.1.0", "react-dom": "18.2.0", "react-hook-form": "^7.50.1", "react-icons": "^5.0.1", + "react-sweetalert2": "^0.6.0", "react-tailwindcss-datepicker": "^1.6.6", "react-tweet": "^3.2.0", + "sweetalert2": "^11.10.8", "sweetalert2-react-content": "^5.0.7", "swiper": "^11.0.6", "tailwind-variants": "^0.1.18", @@ -2773,6 +2777,11 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==" + }, "node_modules/acorn": { "version": "8.11.2", "license": "MIT", @@ -2839,6 +2848,20 @@ "node": ">= 8" } }, + "node_modules/apexcharts": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.49.0.tgz", + "integrity": "sha512-2T9HnbQFLCuYRPndQLmh+bEQFoz0meUbvASaGgiSKDuYhWcLBodJtIpKql2aOtMx4B/sHrWW0dm90HsW4+h2PQ==", + "dependencies": { + "@yr/monotone-cubic-spline": "^1.0.3", + "svg.draggable.js": "^2.2.2", + "svg.easing.js": "^2.0.0", + "svg.filter.js": "^2.0.2", + "svg.pathmorphing.js": "^0.1.3", + "svg.resize.js": "^1.4.3", + "svg.select.js": "^3.0.1" + } + }, "node_modules/arg": { "version": "5.0.2", "license": "MIT" @@ -4845,19 +4868,19 @@ } }, "node_modules/jodit": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/jodit/-/jodit-4.1.16.tgz", - "integrity": "sha512-rqBGuYkmaU4cJrmid2vtdBFMA0eCFp6S7qhP2aNf92wBiLYmo+UnvyW08lH+CcZ2ZoWtVjEiqzGMvj8kZ0zsKA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/jodit/-/jodit-4.2.7.tgz", + "integrity": "sha512-v3UbHMcQLRrrDN/s2tEg+jsOmW7E9BqSJnLbsV0OLT9JAHcsoOpMcxgWYXXXC5mCGOTuJKzikXowuBCfRE4Jsg==", "dependencies": { "autobind-decorator": "^2.4.0" } }, "node_modules/jodit-react": { - "version": "4.0.25", - "resolved": "https://registry.npmjs.org/jodit-react/-/jodit-react-4.0.25.tgz", - "integrity": "sha512-HFbbpabQlE3UdD5mOVm/ZHCRVMtNHCy5oZi4mWquM1W6uNrQG5sO7GuIYTxmW84qfTpuKPWjyw2q1ov/YFW8ug==", + "version": "4.0.28", + "resolved": "https://registry.npmjs.org/jodit-react/-/jodit-react-4.0.28.tgz", + "integrity": "sha512-u3v2cTekJU4F8SCOU1kMKwgqUBclPNCuLtsIZGH5qktTx5cx+xPVWJZyJmozN+YwzBHOP0xg/9VjkSQEtE/rfA==", "dependencies": { - "jodit": "^4.1.16" + "jodit": "^4.2.7" }, "peerDependencies": { "react": "~0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", @@ -5584,6 +5607,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-apexcharts": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz", + "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "apexcharts": "^3.41.0", + "react": ">=0.13" + } + }, "node_modules/react-datepicker": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.6.0.tgz", @@ -5720,6 +5755,18 @@ } } }, + "node_modules/react-sweetalert2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/react-sweetalert2/-/react-sweetalert2-0.6.0.tgz", + "integrity": "sha512-4MEWGAJamSfoj56m7MUs7IfBnev9wJYs0RayvoHvxshSQeH62iK0N/EkDiHr3VuZ3vTy34kOpzL1Yg3b3VYF8w==", + "dependencies": { + "sweetalert2": "^11.7.5" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, "node_modules/react-tailwindcss-datepicker": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/react-tailwindcss-datepicker/-/react-tailwindcss-datepicker-1.6.6.tgz", @@ -6214,11 +6261,93 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg.draggable.js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", + "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "dependencies": { + "svg.js": "^2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.easing.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", + "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "dependencies": { + "svg.js": ">=2.3.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.filter.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", + "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" + }, + "node_modules/svg.pathmorphing.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", + "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "dependencies": { + "svg.js": "^2.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", + "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "dependencies": { + "svg.js": "^2.6.5", + "svg.select.js": "^2.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js/node_modules/svg.select.js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", + "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.select.js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", + "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "dependencies": { + "svg.js": "^2.6.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/sweetalert2": { - "version": "11.10.7", - "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.7.tgz", - "integrity": "sha512-5Jlzrmaitay6KzU+2+LhYu9q+L4v/dZ8oZyEDH14ep0C/QilCnFLHmqAyD/Lhq/lm5DiwsOs6Tr58iv8k3wyGg==", - "peer": true, + "version": "11.10.8", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.8.tgz", + "integrity": "sha512-oAkYROBfXBY+4sVbQEIcN+ZxAx69lsmz5WEBwdEpyS4m59vOBNlRU5/fJpAI1MVfiDwFZiGwVzB/KBpOyfLNtg==", "funding": { "type": "individual", "url": "https://github.com/sponsors/limonte" @@ -6731,9 +6860,12 @@ } }, "node_modules/zod": { - "version": "1.11.17", - "resolved": "https://registry.npmjs.org/zod/-/zod-1.11.17.tgz", - "integrity": "sha512-UzIwO92D0dSFwIRyyqAfRXICITLjF0IP8tRbEK/un7adirMssWZx8xF/1hZNE7t61knWZ+lhEuUvxlu2MO8qqA==" + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 5e8e08f..ff2d53e 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@types/react": "18.2.21", "@types/react-datepicker": "^6.0.1", "@types/react-dom": "18.2.7", + "apexcharts": "^3.48.0", "autoprefixer": "10.4.16", "axios": "^1.6.8", "clsx": "^2.0.0", @@ -42,12 +43,15 @@ "next-themes": "^0.2.1", "postcss": "8.4.31", "react": "18.2.0", + "react-apexcharts": "^1.4.1", "react-datepicker": "^6.1.0", "react-dom": "18.2.0", "react-hook-form": "^7.50.1", "react-icons": "^5.0.1", + "react-sweetalert2": "^0.6.0", "react-tailwindcss-datepicker": "^1.6.6", "react-tweet": "^3.2.0", + "sweetalert2": "^11.10.8", "sweetalert2-react-content": "^5.0.7", "swiper": "^11.0.6", "tailwind-variants": "^0.1.18", @@ -55,4 +59,4 @@ "typescript": "5.0.4", "zod": "^1.11.17" } -} +} \ No newline at end of file diff --git a/public/assets/Footer.jpg b/public/assets/Footer.jpg new file mode 100644 index 0000000..7b9eb8c Binary files /dev/null and b/public/assets/Footer.jpg differ diff --git a/public/humas5.png b/public/humas5.png new file mode 100644 index 0000000..e282605 Binary files /dev/null and b/public/humas5.png differ diff --git a/public/portal-humas.png b/public/portal-humas.png new file mode 100644 index 0000000..f144c61 Binary files /dev/null and b/public/portal-humas.png differ diff --git a/public/portal-humas1.png b/public/portal-humas1.png new file mode 100644 index 0000000..05e4932 Binary files /dev/null and b/public/portal-humas1.png differ diff --git a/public/sertifikat.png b/public/sertifikat.png new file mode 100644 index 0000000..80b96f4 Binary files /dev/null and b/public/sertifikat.png differ diff --git a/public/temp/mediahub1.png b/public/temp/mediahub1.png new file mode 100644 index 0000000..f26cb57 Binary files /dev/null and b/public/temp/mediahub1.png differ diff --git a/public/temp/mediahub2.png b/public/temp/mediahub2.png new file mode 100644 index 0000000..a4685e9 Binary files /dev/null and b/public/temp/mediahub2.png differ diff --git a/service/article.ts b/service/article.ts new file mode 100644 index 0000000..57c8ade --- /dev/null +++ b/service/article.ts @@ -0,0 +1,13 @@ +import { httpGet, httpPost } from "./http-config/axios-base-service"; + +export async function getListArticle() { + const headers = { + "content-type": "application/json", + }; + return await httpGet(`/articles`, headers); +} + +export async function createArticle(data: any) { + const pathUrl = `/articles`; + return await httpPost(pathUrl, data); +} \ No newline at end of file diff --git a/service/http-config/axios-base-service.ts b/service/http-config/axios-base-service.ts new file mode 100644 index 0000000..4d26451 --- /dev/null +++ b/service/http-config/axios-base-service.ts @@ -0,0 +1,48 @@ +import axiosBaseInstance from "./http-base-service"; + +export async function httpPost(pathUrl: any, headers: any, data?: any) { + const response = await axiosBaseInstance + .post(pathUrl, data, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpGet(pathUrl: any, headers: any) { + const response = await axiosBaseInstance + .get(pathUrl, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + diff --git a/service/http-config/http-base-service.ts b/service/http-config/http-base-service.ts new file mode 100644 index 0000000..d195a7f --- /dev/null +++ b/service/http-config/http-base-service.ts @@ -0,0 +1,12 @@ +import axios from "axios"; + +const baseURL = "http://103.82.242.92:8888"; + +const axiosBaseInstance = axios.create({ + baseURL, + headers: { + "content-type": "application/json", + }, +}); + +export default axiosBaseInstance; diff --git a/styles/globals.css b/styles/globals.css index 2d72638..62aae12 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -8,8 +8,9 @@ border:1px solid green; } */ + .custom-scrollbar::-webkit-scrollbar { - width: 12px; + width: 1px; } .custom-scrollbar::-webkit-scrollbar-track { @@ -17,6 +18,18 @@ } .custom-scrollbar::-webkit-scrollbar-thumb { + background: rgb(190, 189, 189); + border-radius: 3px; +} + +.custom-scrollbar::-webkit-scrollbar-thumb:hover { background: transparent; - border-radius: 5px; -} \ No newline at end of file +} + +.hidden-tooltip { + display: none; +} + +.sidebar-scrollbar { + --scroll-shadow-size: 40px; +} diff --git a/types/globals.tsx b/types/globals.tsx new file mode 100644 index 0000000..2408a4e --- /dev/null +++ b/types/globals.tsx @@ -0,0 +1,26 @@ +import { SVGProps } from "react"; + +export type IconSvgProps = SVGProps & { + size?: number; +}; + +export type SidebarMenuTask = { + childMenu: any[]; + name: string; + id: number; + parentId: number; + position: number; + statusId: number; + statusName: string; +}; + +export type Article = { + id: number; + title: string; + articleCategory: string; + updated_at: string; + creator: string; + source: string; + status: string; + actions: string; +};