fix:mobile admin feat:detail comment
This commit is contained in:
parent
19e019fbe9
commit
308e708a3f
|
|
@ -4,7 +4,7 @@ import { Card } from "@nextui-org/react";
|
|||
|
||||
export default function CreateArticle() {
|
||||
return (
|
||||
<div className="bg-transparent p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<div className="bg-transparent p-3 lg:p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
{/* <FormArticle /> */}
|
||||
<CreateArticleForm />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import EditArticleForm from "@/components/form/article/edit-article-form";
|
|||
|
||||
export default function DetailArticlePage() {
|
||||
return (
|
||||
<div className="h-[96vh] bg-transparent p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<div className="h-[96vh] bg-transparent p-3 lg:p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
{/* <FormDetailArticle /> */}
|
||||
<EditArticleForm isDetail={true} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import EditArticleForm from "@/components/form/article/edit-article-form";
|
|||
|
||||
export default function UpdateArticlePage() {
|
||||
return (
|
||||
<div className="h-[96vh] bg-transparent p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<div className="h-[96vh] bg-transparent p-3 lg:p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<EditArticleForm isDetail={false} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,9 +10,12 @@ export default function BasicPage() {
|
|||
return (
|
||||
<div className="overflow-x-hidden overflow-y-scroll">
|
||||
<div className="px-2 md:px-4 md:py-4 w-full">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl py-3">
|
||||
<Link href="/admin/article/create" className="mx-3">
|
||||
<Button size="md" className="bg-[#F07C00] text-white">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl p-3">
|
||||
<Link href="/admin/article/create">
|
||||
<Button
|
||||
size="md"
|
||||
className="bg-[#F07C00] text-white w-full lg:w-fit"
|
||||
>
|
||||
Tambah Artikel
|
||||
<AddIcon />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import DashboardContainer from "@/components/main/dashboard/dashboard-container"
|
|||
export default function AdminPage() {
|
||||
return (
|
||||
<div className="h-[96vh] overflow-x-hidden overflow-y-scroll gap-0 grid">
|
||||
<div className="px-4">
|
||||
<div className="lg:px-4 !w-screen lg:!w-auto">
|
||||
<DashboardContainer />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import React from "react";
|
|||
|
||||
const AdminMagazineCreate = () => {
|
||||
return (
|
||||
<div className="h-[96vh] bg-transparent p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<div className="h-[96vh] bg-transparent p-3 lg:p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<NewCreateMagazineForm />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import EditMagazineForm from "@/components/form/magazine/edit-magazine-form";
|
|||
|
||||
export default function DetailArticlePage() {
|
||||
return (
|
||||
<div className="h-[96vh] bg-transparent p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<div className="h-[96vh] bg-transparent p-3 lg:p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<EditMagazineForm isDetail={true} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import EditMagazineForm from "@/components/form/magazine/edit-magazine-form";
|
|||
|
||||
export default function EditArticlePage() {
|
||||
return (
|
||||
<div className="h-[96vh] bg-transparent p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<div className="h-[96vh] bg-transparent p-3 lg:p-8 !bg-slate-100 dark:!bg-black overflow-y-auto">
|
||||
<EditMagazineForm isDetail={false} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ export default function MagazineTablePage() {
|
|||
return (
|
||||
<div className="overflow-x-hidden overflow-y-scroll">
|
||||
<div className="px-2 md:px-4 md:py-4 w-full">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl py-3">
|
||||
<Link href="/admin/magazine/create" className="mx-3">
|
||||
<Button size="md" className="bg-[#F07C00] text-white">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl p-3">
|
||||
<Link href="/admin/magazine/create">
|
||||
<Button
|
||||
size="md"
|
||||
className="bg-[#F07C00] text-white w-full lg:w-fit"
|
||||
>
|
||||
Tambah Majalah
|
||||
<AddIcon />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -164,10 +164,10 @@ export default function MasterCategoryTable() {
|
|||
return (
|
||||
<div className="overflow-x-hidden overflow-y-scroll">
|
||||
<div className="px-2 md:px-4 md:py-4 w-full">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl py-3">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl p-3">
|
||||
<Button
|
||||
size="md"
|
||||
className="bg-[#F07C00] text-white mx-3"
|
||||
className="bg-[#F07C00] text-white w-full lg:w-fit"
|
||||
onPress={onOpen}
|
||||
>
|
||||
Tambah Kategori
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ export default function StaticPageGeneratorList() {
|
|||
return (
|
||||
<div className="overflow-x-hidden overflow-y-scroll rounded-lg">
|
||||
<div className="px-2 md:px-4 md:py-4 w-full">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl py-3">
|
||||
<Link href="/admin/static-page/create" className="mx-3">
|
||||
<div className="bg-white shadow-lg dark:bg-[#18181b] rounded-xl p-3">
|
||||
<Link href="/admin/static-page/create">
|
||||
<Button
|
||||
size="md"
|
||||
color="primary"
|
||||
className="bg-[#F07C00] text-white"
|
||||
className="bg-[#F07C00] text-white w-full lg:w-fit"
|
||||
>
|
||||
Tambah Halaman
|
||||
<AddIcon />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
import PasswordForm from "@/components/form/settings/password";
|
||||
import ProfileForm from "@/components/form/settings/profile";
|
||||
import { close, loading } from "@/config/swal";
|
||||
import { getProfile } from "@/service/master-user";
|
||||
import { Tab, Tabs } from "@nextui-org/react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
|
@ -11,11 +12,13 @@ export default function Settings() {
|
|||
initFetch();
|
||||
}, []);
|
||||
const initFetch = async () => {
|
||||
loading();
|
||||
const profile = await getProfile();
|
||||
setProfile(profile?.data?.data);
|
||||
close();
|
||||
};
|
||||
return (
|
||||
<div className="w-full lg:w-[60%] p-5">
|
||||
<div className="w-full lg:w-[60%] p-3">
|
||||
<div className="flex flex-col bg-gray-50 shadow-md dark:bg-stone-900 text-black dark:text-white rounded-md p-5">
|
||||
<Tabs aria-label="Tabs radius" radius="sm">
|
||||
<Tab key="profile" title="Profile">
|
||||
|
|
|
|||
|
|
@ -410,10 +410,10 @@ export default function CreateArticleForm() {
|
|||
|
||||
return (
|
||||
<form
|
||||
className="flex flex-row gap-8 text-black"
|
||||
className="flex flex-col lg:flex-row gap-8 text-black"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<div className="w-[65%] bg-white rounded-lg p-8 flex flex-col gap-1">
|
||||
<div className="w-full lg:w-[65%] bg-white rounded-lg p-8 flex flex-col gap-1">
|
||||
<p className="text-sm">Judul</p>
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -527,7 +527,7 @@ export default function CreateArticleForm() {
|
|||
) : null}
|
||||
</Fragment>
|
||||
</div>
|
||||
<div className="w-[35%] flex flex-col gap-8">
|
||||
<div className="w-full lg:w-[35%] flex flex-col gap-8">
|
||||
<div className="h-fit bg-white rounded-lg p-8 flex flex-col gap-1">
|
||||
<p className="text-sm">Thubmnail</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -372,10 +372,10 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
|
||||
return (
|
||||
<form
|
||||
className="flex flex-row gap-8 text-black"
|
||||
className="flex flex-col lg:flex-row gap-8 text-black"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<div className="w-[65%] bg-white rounded-lg p-8 flex flex-col gap-1">
|
||||
<div className="w-full lg:w-[65%] bg-white rounded-lg p-8 flex flex-col gap-1">
|
||||
{isDetail && <GetSeoScore id={String(diseId)} />}
|
||||
<p className="text-sm">Judul</p>
|
||||
<Controller
|
||||
|
|
@ -580,7 +580,7 @@ export default function EditArticleForm(props: { isDetail: boolean }) {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-[35%] flex flex-col gap-8">
|
||||
<div className="w-full lg:w-[35%] flex flex-col gap-8">
|
||||
<div className="h-fit bg-white rounded-lg p-8 flex flex-col gap-1">
|
||||
<p className="text-sm">Thubmnail</p>
|
||||
{isDetail ? (
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ export default function NewCreateMagazineForm() {
|
|||
<div className="flex gap-3 grow">
|
||||
<div className="file-preview">{renderPreview(file)}</div>
|
||||
|
||||
<div className="flex flex-col gap-1 grow">
|
||||
<div className="flex flex-col gap-1 grow w-[45vw] md:w-auto">
|
||||
<p className="text-sm font-semibold">Nama File</p>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<p className=" text-sm text-card-foreground">{file.name}</p>
|
||||
|
|
@ -446,7 +446,9 @@ export default function NewCreateMagazineForm() {
|
|||
</div>
|
||||
{files.length ? (
|
||||
<Fragment>
|
||||
<div className="grid grid-cols-2 gap-2">{fileList}</div>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
|
||||
{fileList}
|
||||
</div>
|
||||
{files.length > 1 && (
|
||||
<div className=" flex justify-between gap-2">
|
||||
<Button onPress={() => setFiles([])} size="sm">
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
|||
<div className="flex gap-3 grow">
|
||||
<div className="file-preview">{renderPreview(file)}</div>
|
||||
|
||||
<div className="flex flex-col gap-1 grow">
|
||||
<div className="flex flex-col gap-1 grow w-[45vw] md:w-auto">
|
||||
<p className="text-sm font-semibold">Nama File</p>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<p className=" text-sm text-card-foreground">{file.name}</p>
|
||||
|
|
@ -557,7 +557,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
|
||||
{files.length ? (
|
||||
<Fragment>
|
||||
{fileList}
|
||||
|
|
@ -574,14 +574,14 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
|||
{detailfiles?.map((file: any, index: number) => (
|
||||
<div
|
||||
key={file.fileName + index}
|
||||
className=" flex justify-between border p-3 rounded-md"
|
||||
className=" flex flex-row lg:justify-between border p-3 rounded-md grow"
|
||||
>
|
||||
<div className="flex gap-3 grow">
|
||||
<div className="file-preview">
|
||||
{renderPreview(file, file.fileName)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 grow">
|
||||
<div className="flex flex-col grow gap-1 w-[45vw] md:w-auto">
|
||||
<p className="text-sm font-semibold">Nama File</p>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<p className=" text-sm text-card-foreground">
|
||||
|
|
@ -644,7 +644,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
|||
</div>
|
||||
|
||||
<Button
|
||||
className=" border-none rounded-full"
|
||||
className=" border-none rounded-full m-0 p-0"
|
||||
variant="bordered"
|
||||
color="danger"
|
||||
onClick={() => handleDeleteFile(file?.id)}
|
||||
|
|
@ -657,7 +657,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
|||
</Fragment>
|
||||
)}
|
||||
{isDetail && (
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
|
||||
{detailfiles?.map((file: any, index: number) => (
|
||||
<div
|
||||
key={file.fileName + index}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,38 @@ export default function ProfileForm(props: {
|
|||
|
||||
return (
|
||||
<form className="flex flex-col gap-3 " onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">Username</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="username"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="username"
|
||||
placeholder=""
|
||||
label=""
|
||||
isReadOnly
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.username && (
|
||||
<p className="text-red-400 text-sm mb-3">
|
||||
{errors.username?.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">Nama Lengkap</p>
|
||||
<Controller
|
||||
|
|
@ -131,37 +163,6 @@ export default function ProfileForm(props: {
|
|||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">Username</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="username"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="username"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.username && (
|
||||
<p className="text-red-400 text-sm mb-3">
|
||||
{errors.username?.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">Email</p>
|
||||
|
|
|
|||
|
|
@ -2178,14 +2178,16 @@ export const TimesIcon = ({
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
width={size || width}
|
||||
height={size || height}
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
strokeWidth="1.5"
|
||||
stroke="currentColor"
|
||||
className="size-6"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6 18 18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
|
|
@ -2208,9 +2210,9 @@ export const CalendarIcon = ({
|
|||
<path fill="currentColor" d="M4 7v2h16V7a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2" />
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="M16 5h2a2 2 0 0 1 2 2v2H4V7a2 2 0 0 1 2-2h2m8 0V3m0 2H8m0-2v2M4 9.5V19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9.5"
|
||||
/>
|
||||
</g>
|
||||
|
|
@ -2350,3 +2352,25 @@ export const CloudUploadIcon = ({
|
|||
/>
|
||||
</svg>
|
||||
);
|
||||
export const BurgerButtonIcon = ({
|
||||
size,
|
||||
height = 24,
|
||||
width = 24,
|
||||
fill = "currentColor",
|
||||
...props
|
||||
}: IconSvgProps) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size || width}
|
||||
height={size || height}
|
||||
{...props}
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
d="M0 3.75A.75.75 0 0 1 .75 3h14.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 3.75M0 8a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H.75A.75.75 0 0 1 0 8m.75 3.5a.75.75 0 0 0 0 1.5h14.5a.75.75 0 0 0 0-1.5z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,11 @@ export default function HeaderNews() {
|
|||
<Card isFooterBlurred radius="lg" className="border-none">
|
||||
<img
|
||||
alt="headernews"
|
||||
src={newsItem.thumbnailUrl}
|
||||
src={
|
||||
newsItem?.thumbnailUrl == ""
|
||||
? "no-image.jpg"
|
||||
: newsItem?.thumbnailUrl
|
||||
}
|
||||
className="h-[25vh] object-cover"
|
||||
/>
|
||||
|
||||
|
|
@ -113,7 +117,9 @@ export default function HeaderNews() {
|
|||
>
|
||||
<img
|
||||
alt="headernews"
|
||||
src={data.thumbnailUrl}
|
||||
src={
|
||||
data?.thumbnailUrl == "" ? "no-image.jpg" : data?.thumbnailUrl
|
||||
}
|
||||
className="object-cover w-[18%] rounded-md"
|
||||
/>
|
||||
<div>
|
||||
|
|
@ -193,7 +199,11 @@ export default function HeaderNews() {
|
|||
>
|
||||
<img
|
||||
alt="headernews"
|
||||
src={newsItem.thumbnailUrl}
|
||||
src={
|
||||
newsItem?.thumbnailUrl == ""
|
||||
? "no-image.jpg"
|
||||
: newsItem?.thumbnailUrl
|
||||
}
|
||||
className="w-full h-[67vh] object-cover rounded-lg"
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => {
|
|||
<SidebarProvider>
|
||||
<div className="!h-screen flex items-center flex-row !overflow-y-hidden">
|
||||
<Sidebar sidebarData={isOpen} updateSidebarData={updateSidebarData} />
|
||||
<SidebarMobile
|
||||
sidebarData={isOpen}
|
||||
updateSidebarData={updateSidebarData}
|
||||
/>
|
||||
<div className={`w-full h-full flex flex-col overflow-hidden`}>
|
||||
<Breadcrumb />
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -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: <DashboardIcon />,
|
||||
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: <ArticleIcon size={24} />,
|
||||
position: 1,
|
||||
statusId: 1,
|
||||
childMenu: [],
|
||||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
name: "Kategori",
|
||||
moduleId: 654,
|
||||
moduleName: "Master",
|
||||
modulePathUrl: "/admin/master-category",
|
||||
parentId: -1,
|
||||
icon: <MasterCategoryIcon size={22} />,
|
||||
position: 1,
|
||||
statusId: 1,
|
||||
childMenu: [],
|
||||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Majalah",
|
||||
moduleId: 652,
|
||||
moduleName: "Apps",
|
||||
modulePathUrl: "/admin/magazine",
|
||||
parentId: -1,
|
||||
icon: <MagazineIcon size={23} />,
|
||||
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: <TableIcon />,
|
||||
// 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: <FormCustomIcon />,
|
||||
// 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: <FormHorizontalIcon />,
|
||||
// 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: <StaticPageIcon size={24} />,
|
||||
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: <MasterUsersIcon />,
|
||||
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: <MasterRoleIcon />,
|
||||
position: 1,
|
||||
statusId: 1,
|
||||
childMenu: [],
|
||||
statusName: "Active",
|
||||
childModule: null,
|
||||
},
|
||||
];
|
||||
|
||||
const SidebarMobile: React.FC<SidebarProps> = ({ updateSidebarData }) => {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const [sidebarMenu, setSidebarMenu] = useState<SidebarMenuTask[]>();
|
||||
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 (
|
||||
<div
|
||||
className={`flex lg:hidden absolute h-screen flex-grow ${
|
||||
isOpen ? "min-w-[240px]" : "hidden"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={` flex h-full flex-col p-4 mb-0 bg-gray-950 z-40 transition-width !ease-in-out justify-between ${
|
||||
isOpen ? "w-[238px]" : "w-[80px]"
|
||||
}`}
|
||||
>
|
||||
<div>
|
||||
{!isOpen && (
|
||||
<div className="w-full flex justify-center items-center">
|
||||
<button
|
||||
className="w-5 h-5 mb-3 text-zinc-400 dark:text-zinc-400 z-50 border-1 border-zinc-400 rounded-full flex justify-center items-center"
|
||||
onClick={toggleSidebar}
|
||||
>
|
||||
<ChevronRightIcon />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`flex ${
|
||||
isOpen ? "justify-between" : "justify-center"
|
||||
} w-full items-center px-2`}
|
||||
>
|
||||
<Link
|
||||
href="/"
|
||||
className="flex flex-row items-center gap-3 font-bold"
|
||||
>
|
||||
<img src="/logohumas.png" className="w-20" />
|
||||
{/* {isOpen && <span>ACME</span>} */}
|
||||
</Link>
|
||||
{isOpen && (
|
||||
<button
|
||||
className="w-5 h-5 text-zinc-400 z-50 border-1 border-zinc-400 rounded-full flex justify-center items-center"
|
||||
onClick={toggleSidebar}
|
||||
>
|
||||
<ChevronLeftIcon />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<SidebarMenu>
|
||||
{sideBarDummyData
|
||||
? sideBarDummyData?.map((list: any, index: number) =>
|
||||
list.isGroup ? (
|
||||
<p
|
||||
key={list}
|
||||
className={`font-bold mr-4 text-white ${
|
||||
!isOpen ? "text-center" : ""
|
||||
}`}
|
||||
>
|
||||
{isOpen ? list.name : "..."}
|
||||
</p>
|
||||
) : list.childMenu?.length < 1 ? (
|
||||
<>
|
||||
{isOpen ? (
|
||||
<Link key={list.id} href={list.modulePathUrl}>
|
||||
{/* <div
|
||||
className={`px-3.5 py-2 mr-4 rounded-lg hover:bg-zinc-400 dark:hover:text-zinc-600 flex flex-row gap-2 ${
|
||||
pathname.includes(list.modulePathUrl)
|
||||
? "bg-zinc-600 dark:bg-zinc-300 text-zinc-300 dark:text-zinc-500 font-bold"
|
||||
: "text-zinc-600 dark:text-zinc-400"
|
||||
}`}
|
||||
> */}
|
||||
<div
|
||||
className={`px-3.5 py-2 mr-4 rounded-lg flex flex-row gap-2 ${
|
||||
pathname.includes(list.modulePathUrl)
|
||||
? "bg-white text-black font-bold"
|
||||
: "text-white hover:bg-gray-200 hover:text-black"
|
||||
}`}
|
||||
>
|
||||
{list.icon} {isOpen && list.name}
|
||||
</div>
|
||||
</Link>
|
||||
) : (
|
||||
<Tooltip
|
||||
content={list.name}
|
||||
placement="right"
|
||||
delay={0}
|
||||
closeDelay={0}
|
||||
>
|
||||
<Link key={list.id} href={list.modulePathUrl}>
|
||||
<div
|
||||
className={`py-2 mr-4 rounded-lg hover:bg-zinc-400 dark:hover:text-zinc-600 flex flex-row justify-center gap-1 ${
|
||||
pathname.includes(list.modulePathUrl)
|
||||
? "bg-zinc-300 text-zinc-500 font-bold hover:text-black"
|
||||
: "text-zinc-400 hover:text-black"
|
||||
}`}
|
||||
>
|
||||
{list.icon} {isOpen && list.name}
|
||||
</div>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<SidebarCollapseItems
|
||||
key={list.id}
|
||||
title={list.name}
|
||||
isActive={pathname.includes(list.modulePathUrl)}
|
||||
icon={list.icon}
|
||||
items={[
|
||||
list?.childMenu?.map((item: any) => (
|
||||
<SidebarCollapseSubItems
|
||||
key={item.id}
|
||||
title={item?.name}
|
||||
isActive={pathname.includes(item.modulePathUrl)}
|
||||
isParentActive={pathname.includes(
|
||||
list.modulePathUrl
|
||||
)}
|
||||
path={item.modulePathUrl}
|
||||
icon={item.icon}
|
||||
/>
|
||||
)),
|
||||
]}
|
||||
/>
|
||||
)
|
||||
)
|
||||
: ""}
|
||||
</SidebarMenu>
|
||||
</div>
|
||||
<div
|
||||
className={`mt-12 p-2 flex ${
|
||||
isOpen ? "justify-start ml-2" : "justify-center"
|
||||
} mt-auto flex flex-col items-between`}
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div
|
||||
className={`flex flex-row ${
|
||||
isOpen ? "justify-start" : "justify-center"
|
||||
} gap-2 items-center text-white `}
|
||||
>
|
||||
<ThemeSwitch />
|
||||
{isOpen && "Theme"}
|
||||
</div>
|
||||
{isOpen ? (
|
||||
<Link href="/settings">
|
||||
<div
|
||||
className={`py-2 mr-4 rounded-lg flex flex-row gap-2 ${
|
||||
pathname.includes("/settings")
|
||||
? "bg-white text-black font-bold px-2"
|
||||
: "text-white "
|
||||
}`}
|
||||
>
|
||||
<SettingsIcon /> {isOpen && "Settings"}
|
||||
</div>
|
||||
</Link>
|
||||
) : (
|
||||
<Tooltip
|
||||
content="Setting"
|
||||
placement="right"
|
||||
delay={0}
|
||||
closeDelay={0}
|
||||
>
|
||||
<Link href="/settings">
|
||||
<div
|
||||
className={`py-2 rounded-lg hover:text-zinc-600 flex flex-row justify-center gap-1 ${
|
||||
pathname.includes("/settings")
|
||||
? "bg-zinc-300 text-zinc-500 font-bold "
|
||||
: "text-zinc-400 "
|
||||
}`}
|
||||
>
|
||||
<SettingsIcon /> {isOpen && "Settings"}
|
||||
</div>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isOpen ? (
|
||||
<div className="flex flex-row gap-3 items-center text-white">
|
||||
<UserProfileIcon size={36} />
|
||||
<div className="flex flex-col ">
|
||||
<a className="cursor-pointer ">{username}</a>
|
||||
<a
|
||||
className="hover:text-red-600 underline text-sm cursor-pointer"
|
||||
onClick={() => onLogout()}
|
||||
>
|
||||
Logout
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<Tooltip
|
||||
content="Profile"
|
||||
delay={0}
|
||||
closeDelay={0}
|
||||
placement="right"
|
||||
>
|
||||
<a
|
||||
className={`cursor-pointer flex flex-row ${
|
||||
isOpen ? "justify-start" : "justify-center"
|
||||
} gap-2 items-center text-zinc-600 dark:text-zinc-400 hover:font-semibold hover:text-zinc-700 dark:hover:text-zinc-300`}
|
||||
onClick={toggleSidebar}
|
||||
>
|
||||
<UserProfileIcon size={28} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SidebarMobile;
|
||||
|
|
@ -90,10 +90,10 @@ export default function DashboardContainer() {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="p-8 flex justify-center">
|
||||
<div className="px-2 lg:p-8 flex justify-center">
|
||||
<div className="w-full flex flex-col gap-6">
|
||||
<div className="w-full flex flex-col md:flex-row gap-6 justify-center">
|
||||
<div className="px-8 py-4 justify-between w-full md:w-[37%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col rounded-lg">
|
||||
<div className="w-full flex flex-col lg:flex-row gap-6 justify-center">
|
||||
<div className="px-4 lg:px-8 py-4 justify-between w-full lg:w-[37%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col rounded-lg">
|
||||
<div className="flex justify-between w-full items-center">
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="font-bold text-xl ">{fullname}</p>
|
||||
|
|
@ -111,28 +111,28 @@ export default function DashboardContainer() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full md:w-[20%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="lg:w-[20%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="h-1/2 flex items-center justify-center">
|
||||
<DashboardSpeecIcon />
|
||||
</div>
|
||||
<div className="">Total post</div>
|
||||
<div className="font-semibold text-lg">121</div>
|
||||
</div>
|
||||
<div className="w-full md:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="w-full lg:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="h-1/2 flex items-center justify-center">
|
||||
<DashboardConnectIcon />
|
||||
</div>
|
||||
<div className="">Total views</div>
|
||||
<div className="font-semibold text-lg">154</div>
|
||||
</div>
|
||||
<div className="w-full md:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="w-full lg:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="h-1/2 flex items-center justify-center">
|
||||
<DashboardShareIcon />
|
||||
</div>
|
||||
<div className="">Total share</div>
|
||||
<div className="font-semibold text-lg">154</div>
|
||||
</div>
|
||||
<div className="w-full md:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="w-full lg:w-[15%] h-[160px] shadow-md bg-white dark:bg-[#18181b] flex flex-col justify-center items-center rounded-lg">
|
||||
<div className="h-1/2 flex items-center justify-center">
|
||||
<DashboardCommentIcon size={50} />
|
||||
</div>
|
||||
|
|
@ -140,17 +140,35 @@ export default function DashboardContainer() {
|
|||
<div className="font-semibold text-lg">530</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full flex flex-row gap-6 justify-center ">
|
||||
<div className="border-1 shadow-sm w-full rounded-lg md:w-[55%] p-6 flex flex-col">
|
||||
<div className="w-full flex flex-col lg:flex-row gap-6 justify-center ">
|
||||
<div className="border-1 shadow-sm w-screen rounded-lg lg:w-[55%] p-6 flex flex-col">
|
||||
<div className="flex justify-between mb-3">
|
||||
<div className="font-semibold flex flex-col">
|
||||
Analytics
|
||||
<div className="font-normal text-xs text-gray-600 flex flex-row gap-2">
|
||||
<CheckboxGroup
|
||||
label=""
|
||||
value={analyticsView}
|
||||
orientation="vertical"
|
||||
onValueChange={setAnalyticView}
|
||||
className="lg:hidden"
|
||||
>
|
||||
<Checkbox size="sm" value="visit">
|
||||
Visit
|
||||
</Checkbox>
|
||||
<Checkbox size="sm" value="view" color="success">
|
||||
View
|
||||
</Checkbox>
|
||||
<Checkbox size="sm" value="share" color="warning">
|
||||
Share
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
<CheckboxGroup
|
||||
label=""
|
||||
value={analyticsView}
|
||||
orientation="horizontal"
|
||||
onValueChange={setAnalyticView}
|
||||
className="hidden lg:block"
|
||||
>
|
||||
<Checkbox size="sm" value="visit">
|
||||
Visit
|
||||
|
|
@ -164,11 +182,12 @@ export default function DashboardContainer() {
|
|||
</CheckboxGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row gap-2">
|
||||
<div className="flex flex-col lg:flex-row gap-2">
|
||||
<Button
|
||||
color="primary"
|
||||
variant={typeDate === "monthly" ? "solid" : "bordered"}
|
||||
onClick={() => setTypeDate("monthly")}
|
||||
className="w-[140px] text-xs lg:text-sm h-[30px] lg:h-[40px] rounded-sm lg:rounded-lg"
|
||||
>
|
||||
Bulanan
|
||||
</Button>
|
||||
|
|
@ -176,23 +195,24 @@ export default function DashboardContainer() {
|
|||
color="primary"
|
||||
onClick={() => setTypeDate("weekly")}
|
||||
variant={typeDate === "weekly" ? "solid" : "bordered"}
|
||||
className="w-[140px] text-xs lg:text-sm h-[30px] lg:h-[40px] rounded-sm lg:rounded-lg"
|
||||
>
|
||||
Mingguan
|
||||
</Button>
|
||||
<div className="w-auto md:w-[140px]">
|
||||
<div className="w-[140px]">
|
||||
<Datepicker
|
||||
value={startDateValue}
|
||||
displayFormat="DD/MM/YYYY"
|
||||
asSingle={true}
|
||||
useRange={false}
|
||||
onChange={(e: any) => 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"
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row w-full h-full">
|
||||
<div className="w-full h-full">
|
||||
<div className="w-full h-[30vh] lg:h-full text-black">
|
||||
<ApexChartColumn
|
||||
type={typeDate}
|
||||
date={getMonthYear(startDateValue.startDate)}
|
||||
|
|
@ -201,7 +221,7 @@ export default function DashboardContainer() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-[45%] gap-6 shadow-md bg-white dark:bg-[#18181b] rounded-lg p-8">
|
||||
<div className="flex flex-col w-full lg:w-[45%] gap-6 shadow-md bg-white dark:bg-[#18181b] rounded-lg p-8">
|
||||
<div className="flex justify-between">
|
||||
<p>Recent Article</p>
|
||||
<Link href="/admin/article/create">
|
||||
|
|
@ -220,7 +240,7 @@ export default function DashboardContainer() {
|
|||
className="h-[70px] w-[70px] object-cover rounded-lg"
|
||||
/>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p>{textEllipsis(list?.title, 40)}</p>
|
||||
<p>{textEllipsis(list?.title, 58)}</p>
|
||||
<p className="text-xs">
|
||||
{convertDateFormat(list?.createdAt)}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ import * as z from "zod";
|
|||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { otpRequest, otpValidation } 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";
|
||||
|
||||
const userId = Cookies.get("uie");
|
||||
|
||||
const commentSchema = z.object({
|
||||
name: z.string().min(1, {
|
||||
|
|
@ -24,6 +29,23 @@ const commentSchema = z.object({
|
|||
}),
|
||||
});
|
||||
|
||||
const dummyData = [
|
||||
{
|
||||
id: 1,
|
||||
createdByName: "User 2",
|
||||
comment: "test comment",
|
||||
createdAt: "2025-01-30T00:09:39.352384Z",
|
||||
createdById: 32,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
createdByName: "User 2",
|
||||
comment: "test comment 22",
|
||||
createdAt: "2025-01-31T00:10:50.352384Z",
|
||||
createdById: 23,
|
||||
},
|
||||
];
|
||||
|
||||
export default function Comment() {
|
||||
const [needOtp, setNeedOtp] = useState(false);
|
||||
const [otpValue, setOtpValue] = useState("");
|
||||
|
|
@ -61,130 +83,159 @@ export default function Comment() {
|
|||
}
|
||||
};
|
||||
return (
|
||||
<form className="p-3 flex flex-col gap-3" onSubmit={handleSubmit(onSubmit)}>
|
||||
<b>Tinggalkan balasan</b>
|
||||
<p className="text-xs">
|
||||
Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai{" "}
|
||||
<span className="text-red-600">*</span>
|
||||
</p>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">Komentar</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="comment"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Textarea
|
||||
type="text"
|
||||
id="comment"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.comment && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.comment?.message}</p>
|
||||
)}
|
||||
<div className="py-5 px-8 flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-2 text-black">
|
||||
{dummyData.map((list) => (
|
||||
<div
|
||||
key={list?.id}
|
||||
className="flex justify-between items-center border-b-2 py-3 shadow-md px-4 rounded-md"
|
||||
>
|
||||
<div className="flex flex-row gap-2 ">
|
||||
<UserProfileIcon size={44} />
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm font-semibold">{list.createdByName}</p>
|
||||
<p className="text-sm">{list.comment}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 text-right">
|
||||
<p className="text-xs">{convertDateFormat(list.createdAt)}</p>
|
||||
{(userId === String(list.createdById) || userId === "16") && (
|
||||
<a className="text-danger cursor-pointer text-xs">Hapus</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">
|
||||
Nama <span className="text-red-600">*</span>
|
||||
<form
|
||||
className="py-3 px-4 flex flex-col gap-3 bg-gray-50 text-black dark:bg-stone-900 dark:text-white rounded-lg shadow-md"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<b>Tinggalkan balasan</b>
|
||||
<p className="text-xs">
|
||||
Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai{" "}
|
||||
<span className="text-red-600">*</span>
|
||||
</p>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="name"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.name && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">
|
||||
Email <span className="text-red-600">*</span>
|
||||
</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="email"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="email"
|
||||
id="email"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.email && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.email?.message}</p>
|
||||
)}
|
||||
</div>
|
||||
{needOtp && (
|
||||
<div className="flex flex-col gap-1">
|
||||
<p>OTP</p>
|
||||
<Input
|
||||
type="number"
|
||||
id="otp"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={otpValue}
|
||||
onValueChange={setOtpValue}
|
||||
labelPlacement="outside"
|
||||
className="w-[100px] "
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
variant="bordered"
|
||||
<p className="text-sm">Komentar</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="comment"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Textarea
|
||||
type="text"
|
||||
id="comment"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.comment && (
|
||||
<p className="text-red-400 text-sm mb-3">
|
||||
{errors.comment?.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">
|
||||
Nama <span className="text-red-600">*</span>
|
||||
</p>
|
||||
|
||||
<Button className="bg-[#DD8306] text-white" radius="md" type="submit">
|
||||
Kirim
|
||||
</Button>
|
||||
</form>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="text"
|
||||
id="name"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.name && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.name?.message}</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm">
|
||||
Email <span className="text-red-600">*</span>
|
||||
</p>
|
||||
<Controller
|
||||
control={control}
|
||||
name="email"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Input
|
||||
type="email"
|
||||
id="email"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
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"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.email && (
|
||||
<p className="text-red-400 text-sm mb-3">{errors.email?.message}</p>
|
||||
)}
|
||||
</div>
|
||||
{needOtp && (
|
||||
<div className="flex flex-col gap-1">
|
||||
<p>OTP</p>
|
||||
<Input
|
||||
type="number"
|
||||
id="otp"
|
||||
placeholder=""
|
||||
label=""
|
||||
value={otpValue}
|
||||
onValueChange={setOtpValue}
|
||||
labelPlacement="outside"
|
||||
className="w-[100px] "
|
||||
classNames={{
|
||||
inputWrapper: [
|
||||
"border-1 rounded-lg",
|
||||
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||
],
|
||||
}}
|
||||
variant="bordered"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Button className="bg-[#DD8306] text-white" radius="md" type="submit">
|
||||
Kirim
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import Comment from "./comment";
|
|||
import { getArticleById, getListArticle } from "@/service/article";
|
||||
import { useParams } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { ChevronRightIcon } from "@/components/icons";
|
||||
import { ChevronRightIcon, UserIcon } from "@/components/icons";
|
||||
import { close, loading } from "@/config/swal";
|
||||
|
||||
export default function NewsDetailPage() {
|
||||
|
|
@ -36,7 +36,7 @@ export default function NewsDetailPage() {
|
|||
};
|
||||
return (
|
||||
<div className="bg-white">
|
||||
<div className="px-5 lg:px-0 lg:w-[70vw] mx-auto py-8">
|
||||
<div className="px-5 lg:px-0 lg:w-[75vw] lg:mx-auto py-8">
|
||||
<div className="flex flex-row gap-4 items-end text-black">
|
||||
<Link href="/" className=" font-semibold text-lg">
|
||||
Beranda
|
||||
|
|
@ -44,18 +44,18 @@ export default function NewsDetailPage() {
|
|||
<ChevronRightIcon />
|
||||
<p className=" text-lg">Berita</p>
|
||||
</div>
|
||||
<div className="text-black lg:flex bg-white gap-4">
|
||||
<div className="text-black lg:flex lg:justify-around bg-white gap-4 lg:gap-16 w-full">
|
||||
<DetailNews data={detailArticle} listArticle={articles} />
|
||||
<div className="w-auto lg:w-[25%] hidden lg:block">
|
||||
<SidebarDetail />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 text-black dark:bg-stone-900 dark:text-white h-auto my-2 md:my-5 lg:my-10 px-3 lg:px-36 rounded-lg shadow-md">
|
||||
<div className="w-[70%] h-auto my-2 md:my-5 lg:my-10 px-3">
|
||||
<Comment />
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 text-black dark:bg-stone-900 dark:text-white lg:px-24 my-4 lg:my-8 pt-3 lg:pb-4 rounded-lg shadow-md h-fit">
|
||||
<div className="bg-gray-50 text-black dark:bg-stone-900 dark:text-white lg:px-24 my-4 lg:my-8 pt-3 lg:pb-4 rounded-lg shadow-md h-fit ">
|
||||
<RelatedNews />
|
||||
</div>
|
||||
<div className="md:hidden text-black">
|
||||
|
|
|
|||
|
|
@ -23,11 +23,13 @@ import { Button } from "@nextui-org/button";
|
|||
import { usePathname } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { useEffect, useState } from "react";
|
||||
import { image } from "@nextui-org/theme";
|
||||
|
||||
export default function DetailNews(props: { data: any; listArticle: any }) {
|
||||
const { data, listArticle } = props;
|
||||
const [prevArticle, setPrevArticle] = useState("");
|
||||
const [nextArticle, setNextArticle] = useState("");
|
||||
const [imageNow, setImageNow] = useState(0);
|
||||
const pathname = usePathname();
|
||||
const shareText = "Humas Polri";
|
||||
|
||||
|
|
@ -102,7 +104,7 @@ export default function DetailNews(props: { data: any; listArticle: any }) {
|
|||
return { __html: doc.body.innerHTML };
|
||||
}
|
||||
return (
|
||||
<div className="flex flex-col gap-2 py-4">
|
||||
<div className="flex flex-col gap-2 py-4 lg:w-[65%] lg:mx-auto">
|
||||
<p className="font-semibold text-xl lg:text-3xl">{data?.title}</p>
|
||||
<div className="flex flex-row items-center py-1 text-xs lg:text-lg gap-2 lg:gap-4">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
|
|
@ -135,34 +137,51 @@ export default function DetailNews(props: { data: any; listArticle: any }) {
|
|||
<div className="flex justify-center my-2 lg:my-5">
|
||||
<img
|
||||
alt="NextUI hero Image"
|
||||
src={data?.thumbnailUrl}
|
||||
className="object-cover w-[100%]"
|
||||
src={`http://38.47.180.165:8802${data?.files[imageNow]?.file_url}`}
|
||||
className="object-cover w-[100%] rounded-md"
|
||||
/>
|
||||
</div>
|
||||
{data?.files?.length > 1 && (
|
||||
<div className="flex flex-row gap-3 flex-nowrap overflow-x-auto">
|
||||
{data?.files?.map((file: any, index: number) => (
|
||||
<a
|
||||
key={file.id}
|
||||
onClick={() => setImageNow(index)}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<img
|
||||
alt="NextUI hero Image"
|
||||
src={`http://38.47.180.165:8802${file?.file_url}`}
|
||||
className="object-cover h-[50px] lg:h-[100px] rounded-md"
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
dangerouslySetInnerHTML={removeImgTags(
|
||||
formatTextToHtmlTag(data?.htmlDescription)
|
||||
)}
|
||||
className="text-sm lg:text-xl lg:leading-8"
|
||||
className="text-sm lg:text-xl lg:leading-8 text-justify"
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-5 my-8">
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-2 lg:gap-5 my-8">
|
||||
<Button
|
||||
variant="solid"
|
||||
radius="none"
|
||||
onPress={() => handleShare("facebook")}
|
||||
className="w-[80%] bg-[#3b5998] text-white px-4 py-2 flex flex-row"
|
||||
className="lg:w-[80%] bg-[#3b5998] text-white px-4 py-2 flex flex-row"
|
||||
>
|
||||
<div className="w-1/4 ">
|
||||
<SquareFacebookIcon />
|
||||
</div>
|
||||
<div className="w-3/4 text-xl ">Facebook</div>
|
||||
<div className=" text-xl ">Facebook</div>
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
radius="none"
|
||||
onPress={() => handleShare("x")}
|
||||
className="w-[80%] bg-black text-white px-4 py-2 flex flex-row"
|
||||
className="lg:w-[80%] bg-black text-white px-4 py-2 flex flex-row"
|
||||
>
|
||||
<div className="w-1/4 ">
|
||||
<SquareXIcon />
|
||||
|
|
@ -173,7 +192,7 @@ export default function DetailNews(props: { data: any; listArticle: any }) {
|
|||
variant="solid"
|
||||
radius="none"
|
||||
onPress={() => handleShare("linkedin")}
|
||||
className="w-[80%] bg-[#0E76A8] text-white px-4 py-2 flex flex-row"
|
||||
className="lg:w-[80%] bg-[#0E76A8] text-white px-4 py-2 flex flex-row"
|
||||
>
|
||||
<div className="w-1/4 ">
|
||||
<SquareLinkedInIcon />
|
||||
|
|
@ -184,7 +203,7 @@ export default function DetailNews(props: { data: any; listArticle: any }) {
|
|||
variant="solid"
|
||||
radius="none"
|
||||
onPress={() => handleShare("whatsapp")}
|
||||
className="w-[80%] bg-[#25D366] text-white px-4 py-2 flex flex-row"
|
||||
className="lg:w-[80%] bg-[#25D366] text-white px-4 py-2 flex flex-row"
|
||||
>
|
||||
<div className="w-1/4 ">
|
||||
<SquareWhatsappIcon />
|
||||
|
|
|
|||
|
|
@ -69,8 +69,12 @@ export default function RelatedNews() {
|
|||
<Card isFooterBlurred radius="lg" className="border-none">
|
||||
<img
|
||||
alt="headernews"
|
||||
src={newsItem.thumbnailUrl}
|
||||
className="h-[25vh] object-cover rounded-none"
|
||||
src={
|
||||
newsItem?.thumbnailUrl == ""
|
||||
? "/no-image.jpg"
|
||||
: newsItem?.thumbnailUrl
|
||||
}
|
||||
className="!h-[25vh] object-cover rounded-none"
|
||||
/>
|
||||
<CardFooter className="before:bg-white/10 border-white/20 border-1 overflow-hidden py-1 md:absolute bottom-1 shadow-small z-10">
|
||||
<div className="text-black dark:text-white lg:text-white">
|
||||
|
|
|
|||
|
|
@ -56,7 +56,11 @@ export default function SidebarDetail() {
|
|||
<div className="h-[230px] lg:h-[180px] flex flex-col gap-2 bg-gray-50 dark:bg-stone-900 p-5 rounded-lg">
|
||||
<img
|
||||
alt="headernews"
|
||||
src={newsItem.thumbnailUrl}
|
||||
src={
|
||||
newsItem?.thumbnailUrl == ""
|
||||
? "/no-image.jpg"
|
||||
: newsItem?.thumbnailUrl
|
||||
}
|
||||
className="object-cover !h-[70%] rounded-lg"
|
||||
/>
|
||||
<div className="text-black dark:text-white flex flex-col">
|
||||
|
|
@ -106,7 +110,11 @@ export default function SidebarDetail() {
|
|||
<div className="h-[230px] lg:h-[180px] flex flex-col gap-2 bg-gray-50 dark:bg-stone-900 p-5 rounded-lg">
|
||||
<img
|
||||
alt="headernews"
|
||||
src={newsItem.thumbnailUrl}
|
||||
src={
|
||||
newsItem?.thumbnailUrl == ""
|
||||
? "/no-image.jpg"
|
||||
: newsItem?.thumbnailUrl
|
||||
}
|
||||
className="object-cover !h-[70%] rounded-lg"
|
||||
/>
|
||||
<div className="text-black dark:text-white flex flex-col">
|
||||
|
|
|
|||
|
|
@ -225,10 +225,10 @@ export default function ArticleTable() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="p-3">
|
||||
<div className="py-3">
|
||||
<div className="flex flex-col items-start rounded-2xl gap-3">
|
||||
<div className="flex flex-col md:flex-row gap-3 w-full">
|
||||
<div className="flex flex-col gap-1 w-1/3">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-1/3">
|
||||
<p className="font-semibold text-sm">Pencarian</p>
|
||||
<Input
|
||||
aria-label="Search"
|
||||
|
|
@ -246,7 +246,7 @@ export default function ArticleTable() {
|
|||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-[72px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[72px]">
|
||||
<p className="font-semibold text-sm">Data</p>
|
||||
<Select
|
||||
label=""
|
||||
|
|
@ -268,7 +268,7 @@ export default function ArticleTable() {
|
|||
</SelectItem>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-[230px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[230px]">
|
||||
<p className="font-semibold text-sm">Kategori</p>
|
||||
<Select
|
||||
label=""
|
||||
|
|
@ -293,7 +293,7 @@ export default function ArticleTable() {
|
|||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-full md:w-[240px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[240px]">
|
||||
<p className="font-semibold text-sm">Tanggal</p>
|
||||
<Datepicker
|
||||
value={startDateValue}
|
||||
|
|
|
|||
|
|
@ -226,10 +226,10 @@ export default function MagazineTable() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="p-3">
|
||||
<div className="py-3">
|
||||
<div className="flex flex-col items-start rounded-2xl gap-3">
|
||||
<div className="flex flex-col md:flex-row gap-3 w-full">
|
||||
<div className="flex flex-col gap-1 w-1/3">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-1/3">
|
||||
<p className="font-semibold text-sm">Pencarian</p>
|
||||
<Input
|
||||
aria-label="Search"
|
||||
|
|
@ -247,7 +247,7 @@ export default function MagazineTable() {
|
|||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-[72px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[72px]">
|
||||
<p className="font-semibold text-sm">Data</p>
|
||||
<Select
|
||||
label=""
|
||||
|
|
@ -294,7 +294,7 @@ export default function MagazineTable() {
|
|||
))}
|
||||
</Select>
|
||||
</div> */}
|
||||
<div className="flex flex-col gap-1 w-full md:w-[240px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[240px]">
|
||||
<p className="font-semibold text-sm">Tanggal</p>
|
||||
<Datepicker
|
||||
value={startDateValue}
|
||||
|
|
|
|||
|
|
@ -341,10 +341,10 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="p-3">
|
||||
<div className="py-3">
|
||||
<div className="flex flex-col items-start rounded-2xl gap-3">
|
||||
<div className="flex flex-col md:flex-row gap-3 w-full">
|
||||
<div className="flex flex-col gap-1 w-1/3">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-1/3">
|
||||
<p className="font-semibold text-sm">Pencarian</p>
|
||||
<Input
|
||||
aria-label="Search"
|
||||
|
|
@ -362,7 +362,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
|
|||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-[72px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[72px]">
|
||||
<p className="font-semibold text-sm">Data</p>
|
||||
<Select
|
||||
label=""
|
||||
|
|
@ -523,7 +523,7 @@ export default function CategoriesTable(props: { triggerRefresh: boolean }) {
|
|||
onValueChange={setTag}
|
||||
startContent={
|
||||
<div className="flex flex-row gap-1">
|
||||
{value.map((item, index) => (
|
||||
{value?.map((item, index) => (
|
||||
<Chip
|
||||
color="primary"
|
||||
key={index}
|
||||
|
|
|
|||
|
|
@ -200,10 +200,10 @@ export default function StaticPageTable() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="p-3">
|
||||
<div className="py-3">
|
||||
<div className="flex flex-col items-start rounded-2xl gap-3">
|
||||
<div className="flex flex-col md:flex-row gap-3 w-full">
|
||||
<div className="flex flex-col gap-1 w-1/3">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-1/3">
|
||||
<p className="font-semibold text-sm">Pencarian</p>
|
||||
<Input
|
||||
aria-label="Pencarian..."
|
||||
|
|
@ -221,7 +221,7 @@ export default function StaticPageTable() {
|
|||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1 w-[72px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[72px]">
|
||||
<p className="font-semibold text-sm">Data</p>
|
||||
<Select
|
||||
label=""
|
||||
|
|
@ -243,7 +243,7 @@ export default function StaticPageTable() {
|
|||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 w-full md:w-[340px]">
|
||||
<div className="flex flex-col gap-1 w-full lg:w-[340px]">
|
||||
<p className="font-semibold text-sm">Tanggal</p>
|
||||
<Datepicker
|
||||
value={startDateValue}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ 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";
|
||||
import { BurgerButtonIcon, FormLayoutIcon } from "../icons";
|
||||
import {
|
||||
ArticleIcon,
|
||||
DashboardIcon,
|
||||
|
|
@ -13,14 +13,18 @@ import {
|
|||
MasterCategoryIcon,
|
||||
MasterRoleIcon,
|
||||
MasterUsersIcon,
|
||||
MenuBurgerIcon,
|
||||
StaticPageIcon,
|
||||
} from "../icons/sidebar-icon";
|
||||
import { useSidebar } from "../layout/sidebar/sidebar-context";
|
||||
|
||||
export const Breadcrumb = () => {
|
||||
const [currentPage, setCurrentPage] = useState<React.Key>("");
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const pathnameSplit = pathname.split("/");
|
||||
const { isOpen, toggleSidebar } = useSidebar();
|
||||
|
||||
pathnameSplit.shift();
|
||||
let pathnameTransformed = pathnameSplit.map((item) => {
|
||||
let words = item.split("-");
|
||||
|
|
@ -67,16 +71,28 @@ export const Breadcrumb = () => {
|
|||
)}
|
||||
</Breadcrumbs>
|
||||
</div>
|
||||
{pathname.includes("dashboard") && <DashboardIcon size={50} />}
|
||||
{pathname.includes("article") && <ArticleIcon size={50} />}
|
||||
{pathname.includes("master-category") && (
|
||||
<MasterCategoryIcon size={50} />
|
||||
)}
|
||||
{pathname.includes("magazine") && <MagazineIcon size={50} />}
|
||||
{pathname.includes("static-page") && <StaticPageIcon size={50} />}
|
||||
{pathname.includes("master-user") && <MasterUsersIcon size={50} />}
|
||||
{pathname.includes("master-role") && <MasterRoleIcon size={50} />}
|
||||
{/* <FormLayoutIcon width={50} height={50} /> */}
|
||||
<div className="lg:hidden">
|
||||
{!isOpen && (
|
||||
<button
|
||||
className="w-5 h-5 mb-3 text-zinc-400 dark:text-zinc-400 z-50 flex justify-center items-center"
|
||||
onClick={toggleSidebar}
|
||||
>
|
||||
<BurgerButtonIcon />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="hidden lg:block">
|
||||
{pathname.includes("dashboard") && <DashboardIcon size={50} />}
|
||||
{pathname.includes("article") && <ArticleIcon size={50} />}
|
||||
{pathname.includes("master-category") && (
|
||||
<MasterCategoryIcon size={50} />
|
||||
)}
|
||||
{pathname.includes("magazine") && <MagazineIcon size={50} />}
|
||||
{pathname.includes("static-page") && <StaticPageIcon size={50} />}
|
||||
{pathname.includes("master-user") && <MasterUsersIcon size={50} />}
|
||||
{pathname.includes("master-role") && <MasterRoleIcon size={50} />}
|
||||
{/* <FormLayoutIcon width={50} height={50} /> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue