feat:add content rewrite, add create ai image

This commit is contained in:
Anang Yusman 2025-01-01 23:29:13 +08:00
commit f477783e92
21 changed files with 1028 additions and 92 deletions

View File

@ -1,3 +0,0 @@
{
"extends": "next/core-web-vitals"
}

View File

@ -0,0 +1,196 @@
"use client";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { useState } from "react";
import { addDays, format } from "date-fns";
import { Calendar as CalendarIcon } from "lucide-react";
import { DateRange } from "react-day-picker";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
const users = [
{ id: 1, name: "POLRI" },
{ id: 2, name: "JURNALIS" },
];
export default function ContentManagement() {
const [startDate, setStartDate] = useState<any>(new Date());
const [endDate, setEndDate] = useState<any>(new Date());
return (
<div>
<SiteBreadcrumb />
<div className="flex flex-col gap-3">
{users.map((user) => (
<Accordion
key={user.id}
id="polri"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
KONTEN YANG DISIMPAN OLEH PENGGUNA {user.name} INDONESIA
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
))}
{users.map((user) => (
<Accordion
key={user.id}
id={String(user.id)}
type="single"
collapsible
className="w-full"
>
<AccordionItem
value={`${user.id}-value-${user.name}`}
className="bg-white w-full"
>
<AccordionTrigger className="bg-white">
PENAMBAHAN JUMLAH PENGGUNA {user.name} INDONESIA
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
))}
</div>
</div>
);
}

View File

@ -0,0 +1,113 @@
"use client";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { useState } from "react";
import { addDays, format } from "date-fns";
import { Calendar as CalendarIcon } from "lucide-react";
import { DateRange } from "react-day-picker";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
const users = [
{ id: 1, name: "POLRI" },
{ id: 2, name: "JURNALIS" },
];
export default function EmergencyIssue() {
const [startDate, setStartDate] = useState<any>(new Date());
const [endDate, setEndDate] = useState<any>(new Date());
return (
<div>
<SiteBreadcrumb />
<div className="flex flex-col gap-3">
<Accordion
id="feedback-center"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
ANALISA BERKAITAN DENGAN AKUN PELAPOR{" "}
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</div>
);
}

View File

@ -0,0 +1,113 @@
"use client";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { useState } from "react";
import { addDays, format } from "date-fns";
import { Calendar as CalendarIcon } from "lucide-react";
import { DateRange } from "react-day-picker";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
const users = [
{ id: 1, name: "POLRI" },
{ id: 2, name: "JURNALIS" },
];
export default function FeedbackCenter() {
const [startDate, setStartDate] = useState<any>(new Date());
const [endDate, setEndDate] = useState<any>(new Date());
return (
<div>
<SiteBreadcrumb />
<div className="flex flex-col gap-3">
<Accordion
id="feedback-center"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
TICKET PADA FEEDBACK CENTER{" "}
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</div>
);
}

View File

@ -0,0 +1,330 @@
"use client";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { useState } from "react";
import { addDays, format } from "date-fns";
import { Calendar as CalendarIcon } from "lucide-react";
import { DateRange } from "react-day-picker";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
export default function ContentManagement() {
const [startDate, setStartDate] = useState<any>(new Date());
const [endDate, setEndDate] = useState<any>(new Date());
return (
<div>
<SiteBreadcrumb />
<div className="flex flex-col gap-3">
<Accordion
id="schedule-press-conference"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
PUBLISH JADWAL PRESS CONFERENCE TERBANYAK
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
<Accordion
id="content-press-conference"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
JUMLAH PRODUKSI KONTEN UNTUK KATEGORI PRESS CONFERENCE
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
<Accordion
id="interaction-press-conference"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
TINGKAT INTERAKSI KONTEN UNTUK KATEGORI PRESS CONFERENCE
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
<Accordion
id="press-release"
type="single"
collapsible
className="w-full"
>
<AccordionItem value="item-1" className="bg-white w-full">
<AccordionTrigger className="bg-white">
AKTIFITAS MEDIA BERKAITAN DENGAN PERS RILIS
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-row gap-3">
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate}
onSelect={setStartDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
<div className="flex flex-col">
<p>Tanggal Mulai</p>
<Popover>
<PopoverTrigger asChild>
<Button
variant={"outline"}
className={cn(
"w-[280px] justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "PPP")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate}
onSelect={setEndDate}
initialFocus
/>
</PopoverContent>
</Popover>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
</div>
);
}

View File

@ -0,0 +1,10 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
export default function ManagementUser() {
return (
<div>
<SiteBreadcrumb />
<p className="font-semibold">STATISTIK JUMLAH PENGGUNA</p>
</div>
);
}

View File

@ -0,0 +1,10 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
export default function PerformancePolda() {
return (
<div>
<SiteBreadcrumb />
<p className="font-semibold">PERFORMANCE KUMULATIF PER POLDA</p>
</div>
);
}

View File

@ -0,0 +1,9 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
export default function ExecutiveDashboard() {
return (
<div>
<SiteBreadcrumb />
</div>
);
}

View File

@ -50,24 +50,22 @@ const KnowledgeBase = () => {
<TabsList className="md:flex-col gap-2 flex-wrap md:items-start justify-start">
<CreateCategory onSuccess={fetchCategoryList} />
{categories?.map((category: any, index: number) => (
<div>
<TabsTrigger
key={index}
value={`category-${index}`}
onClick={() => {
fetchQuestions(category?.id);
}}
className="data-[state=active]:bg-secondary data-[state=active]:text-default rounded-md px-6 py-3 w-full justify-start"
<TabsTrigger
key={index}
value={`category-${index}`}
onClick={() => {
fetchQuestions(category?.id);
}}
className="data-[state=active]:bg-secondary data-[state=active]:text-default rounded-md px-6 py-3 w-full justify-start"
>
{category?.name}
<div
className="absolute right-2 top-2 hidden group-hover:inline-flex"
// onClick={() => deleteCategory(category?.id)}
>
{category?.name}
<div
className="absolute right-2 top-2 hidden group-hover:inline-flex"
// onClick={() => deleteCategory(category?.id)}
>
<Trash2 className="w-3.5 h-3.5 me-1" />
</div>
</TabsTrigger>
</div>
<Trash2 className="w-3.5 h-3.5 me-1" />
</div>
</TabsTrigger>
))}
</TabsList>
</CardContent>

View File

@ -19,7 +19,7 @@ const dummyContent = [
{ title: "Operasi Zebra Nataru", thumbnail: "/assets/hot-topik-1.jpg", createdAt: "17 Agustus 2025", timezone: "14:20 WIB", clickCount: "28" },
];
const ContentManagement = (props: { type: string }) => {
const ContentManagement = () => {
const [profile, setProfile] = useState<any>();
const [province, setProvince] = useState([]);
const [, setUser] = useState();
@ -85,16 +85,18 @@ const ContentManagement = (props: { type: string }) => {
<div className="flex justify-between mx-10">
<div className="flex items-center gap-2 ">
<img src="/assets/avatar-profile.png" alt="avatar" className="w-14 h-14" />
<p className="text-white">{profile?.fullname}</p>
<p className="text-white">{profile?.username}</p>
<p className="text-white">
Aktif Sejak
{`${new Date(profile?.createdAt).getDate()}/${new Date(profile?.createdAt).getMonth() + 1}/${new Date(profile?.createdAt).getFullYear()} ${new Date(profile?.createdAt).getHours()}:${new Date(
profile?.createdAt
).getMinutes()}`}
</p>
<div className="flex flex-col mx-2">
<p className="text-white text-sm font-semibold">{profile?.fullname}</p>
<p className="text-white text-sm font-light">{profile?.username}</p>
<p className="text-white text-sm font-light">
Aktif Sejak&nbsp;
{`${new Date(profile?.createdAt).getDate()}/${new Date(profile?.createdAt).getMonth() + 1}/${new Date(profile?.createdAt).getFullYear()} ${new Date(profile?.createdAt).getHours()}:${new Date(
profile?.createdAt
).getMinutes()}`}
</p>
</div>
</div>
<Link href="#" className="flex items-center text-white gap-2">
<Link href="/profile" className="flex items-center text-white gap-2">
<Icon icon="tdesign:setting-1-filled" />
Pengaturan
</Link>
@ -110,29 +112,29 @@ const ContentManagement = (props: { type: string }) => {
<div>
<ul className="px-10 mb-4">
<li className="mb-5 font-light">
<p>Email</p>
<p>msabdayagra@gmail.com</p>
{/* <p>{profile?.email}</p> */}
<p className="font-semibold">Email :</p>
{/* <p>msabdayagra@gmail.com</p> */}
<p>{profile?.email}</p>
</li>
<li className="mb-5 font-light">
<p>No Handphone</p>
<p>0812-7561-7204</p>
{/* <p>{profile?.phoneNumber}</p> */}
<p className="font-semibold">No Handphone :</p>
{/* <p>0812-7561-7204</p> */}
<p>{profile?.phoneNumber}</p>
</li>
<li className="mb-5 font-light">
<p>Alamat</p>
<p>Jl. Besar Tembung no.12</p>
{/* <p>{profile?.address}</p> */}
<p className="font-semibold">Alamat :</p>
{/* <p>Jl. Besar Tembung no.12</p> */}
<p>{profile?.address}</p>
</li>
<li className="mb-5 font-light">
<p>Kategori</p>
<p>POLRI</p>
{/* <p>{profile?.institute?.categoryRole?.name}</p> */}
<p className="font-semibold">Kategori :</p>
{/* <p>POLRI</p> */}
<p>{profile?.institute?.categoryRole?.name}</p>
</li>
<li className="mb-5 font-light">
<p>Instansi/Perusahaan</p>
<p>Div Humas Polri</p>
{/* <p>{profile?.institute?.name}</p> */}
<p className="font-semibold">Instansi/Perusahaan :</p>
{/* <p>Div Humas Polri</p> */}
<p>{profile?.institute?.name}</p>
</li>
</ul>
</div>
@ -143,7 +145,7 @@ const ContentManagement = (props: { type: string }) => {
<div className="hover:bg-slate-800 cursor-pointer rounded-lg flex justify-between">
<div className="flex items-center gap-2 text-lg">
<Icon icon="material-symbols-light:perm-media-rounded" />
<p>Galeri Div Humas</p>
<p className="text-sm">Galeri {profile?.institute?.name}</p>
</div>
<div>
<Icon icon="ri:arrow-right-s-line" fontSize={20} />
@ -189,7 +191,7 @@ const ContentManagement = (props: { type: string }) => {
{/* Kontent Kanan */}
<div className="w-2/3 p-12">
<div>
<h1 className="text-2xl font-semibold">Galeri Div Humas</h1>
<h1 className="text-2xl font-semibold">Galeri {profile?.institute?.name}</h1>
</div>
<div className="px-4 lg:px-10 py-4">
<div className="flex flex-col p-4">
@ -228,9 +230,9 @@ const ContentManagement = (props: { type: string }) => {
</div>
<div className="px-0 lg:px-10">
{selectedTab == "video" ? (
dummyContent?.length > 0 ? (
profile?.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{dummyContent?.map((video: any) => (
{profile?.map((video: any) => (
<Card key={video?.id} className="hover:scale-110 transition-transform duration-300">
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<Link href={`/video/detail/${video?.slug}`}>
@ -257,9 +259,9 @@ const ContentManagement = (props: { type: string }) => {
</p>
)
) : selectedTab == "audio" ? (
dummyContent?.length > 0 ? (
profile?.length > 0 ? (
<div className=" grid grid-cols-1 gap-6 ">
{dummyContent?.map((audio: any) => (
{profile?.map((audio: any) => (
<Link
href={`/audio/detail/${audio?.slug}`}
key={audio?.id}
@ -304,16 +306,16 @@ const ContentManagement = (props: { type: string }) => {
</p>
)
) : selectedTab == "image" ? (
dummyContent?.length > 0 ? (
profile?.length > 0 ? (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
{dummyContent?.map((video: any) => (
<Card key={video?.id} className="hover:scale-110 transition-transform duration-300">
{profile?.map((image: any) => (
<Card key={image?.id} className="hover:scale-110 transition-transform duration-300">
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
<Link href={`/video/detail/${video?.slug}`}>
<img src={video?.thumbnail} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" />
<Link href={`/image/detail/${image?.slug}`}>
<img src={image?.thumbnail} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" />
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
{formatDateToIndonesian(new Date(video?.createdAt))} {video?.timezone ? video?.timezone : "WIB"}| <Icon icon="formkit:eye" width="15" height="15" />
{video?.clickCount}{" "}
{formatDateToIndonesian(new Date(image?.createdAt))} {image?.timezone ? image?.timezone : "WIB"}| <Icon icon="formkit:eye" width="15" height="15" />
{image?.clickCount}{" "}
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20">
<path
fill="#f00"
@ -321,7 +323,7 @@ const ContentManagement = (props: { type: string }) => {
/>
</svg>{" "}
</div>
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{video?.title}</div>
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{image?.title}</div>
</Link>
</CardContent>
</Card>
@ -332,9 +334,9 @@ const ContentManagement = (props: { type: string }) => {
<img src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
</p>
)
) : dummyContent.length > 0 ? (
) : profile.length > 0 ? (
<div className=" grid grid-cols-1 md:grid-cols-2 gap-6">
{dummyContent?.map((document: any) => (
{profile?.map((document: any) => (
<Link href={`/document/detail/${document?.slug}`} key={document?.id} className="flex flex-col bg-yellow-500 sm:flex-row items-center dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full">
<div className="flex items-center justify-center rounded-lg w-16 h-16">
<svg width="28" height="34" viewBox="0 0 28 34" fill="none" xmlns="http://www.w3.org/2000/svg">

View File

@ -564,7 +564,7 @@ export default function FormImageAI() {
JIka Anda tidak Memberikan kata kunci, kami akan secara
otomatis membuat kata kunci yang relevan dari kata kunci utama
untuk setiap bagian dan menggunakannya untuk membuat artikel.
Untuk menambahkan kata kunci baru, ketik ', + kata kunci'.
Untuk menambahkan kata kunci baru, ketik &apos;, + kata kunci&apos;.
</p>
<div className="mt-3">
<Textarea

View File

@ -586,8 +586,8 @@ export default function FormImage() {
JIka Anda tidak Memberikan kata kunci, kami akan secara
otomatis membuat kata kunci yang relevan dari kata kunci
utama untuk setiap bagian dan menggunakannya untuk membuat
artikel. Untuk menambahkan kata kunci baru, ketik ', +
kata kunci'.
artikel. Untuk menambahkan kata kunci baru, ketik &apos;, +
kata kunci&apos;.
</p>
<div className="mt-3">
<Textarea

View File

@ -450,12 +450,13 @@ export default function FormConvertSPIT() {
)}
</div>
<div className="my-2">
<p
<Button
size="sm"
onClick={handleRewriteClick}
className="bg-blue-500 text-white py-2 px-4 rounded w-[200px]"
className="bg-blue-500 text-white py-2 px-4 rounded"
>
Content Rewrite
</p>
</Button>
</div>
{showRewriteEditor && (
<div>

View File

@ -371,7 +371,7 @@ const Navbar = () => {
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<Link href="#" className="flex items-center gap-1 hover:bg-slate-600 w-full rounded-lg">
<Link href="/profile" className="flex items-center gap-1 hover:bg-slate-600 w-full rounded-lg">
<Icon icon="iconamoon:profile-circle-fill" />
Profile
</Link>
@ -789,7 +789,50 @@ const Navbar = () => {
</div>
<div className="flex justify-center items-center mx-3 gap-5">
{fullName ? (
<p>{fullName}</p>
<>
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center gap-1">
<img
className="h-12 w-12"
src="/assets/avatar-profile.png"
alt="avatar-profile"
/>
<a className="gap-2">
<p className="text-xs font-semibold">{fullName}</p>
<p className="text-xs">{`(${roleName})`}</p>
</a>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>
<Link
href="/profile"
className="flex items-center gap-1 hover:bg-slate-600 w-full rounded-lg"
>
<Icon icon="iconamoon:profile-circle-fill" />
Profile
</Link>
</DropdownMenuItem>
<DropdownMenuItem>
<Link
href="/content-management"
className="flex items-center gap-1 hover:bg-slate-600 w-full rounded-lg"
>
<Icon icon="stash:save-ribbon-light" />
Kelola Konten
</Link>
</DropdownMenuItem>
<DropdownMenuItem>
<Link
href="#"
className="flex items-center gap-1 hover:bg-slate-600 w-full rounded-lg"
>
<Icon icon="iconamoon:exit-bold" />
Keluar
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
) : (
<>
<Link
@ -806,18 +849,6 @@ const Navbar = () => {
</Link>{" "}
</>
)}
<Link
href="/auth"
className="w-full lg:w-fit px-4 py-1 bg-[#bb3523] text-white font-semibold rounded-md hover:bg-red-700 text-center"
>
Masuk
</Link>
<Link
href="#"
className="w-full lg:w-fit px-4 py-1 border border-[#bb3523] text-[#bb3523] font-semibold rounded-md hover:bg-[#bb3523] text-center hover:text-white"
>
Daftar
</Link>
</div>
</div>
)}

View File

@ -45,7 +45,6 @@ export type Notification = {
};
const getNotificationIcon = (notificationTypeId: number) => {
const router = useRouter();
switch (notificationTypeId) {
case 2:
return <MessageCircle className="h-8 w-8 text-success" />;

13
eslint.config.mjs Normal file
View File

@ -0,0 +1,13 @@
import { FlatCompat } from '@eslint/eslintrc'
const compat = new FlatCompat({
baseDirectory: import.meta.dirname,
})
const eslintConfig = [
...compat.config({
extends: ['next/core-web-vitals', 'next/typescript'],
}),
]
export default eslintConfig

View File

@ -1692,15 +1692,15 @@ export function getMenuList(pathname: string, t: any): Group[] {
submenus: [
{
href: "/dashboard",
label: "Executive",
label: "Breakdown",
active: pathname === "/dashboard",
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/dashboard/breakdown",
label: "Breakdown",
active: pathname === "/dashboard/breakdown",
href: "/dashboard/executive",
label: "Executive",
active: pathname === "/dashboard/executive",
icon: "heroicons:arrow-trending-up",
children: [],
},
@ -1728,7 +1728,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
menus: [
{
id: "management-user-menu",
href: "/adminn/management-user",
href: "/admin/management-user",
label: "Management User",
active: pathname.includes("/management-user"),
icon: "clarity:users-solid",
@ -1790,9 +1790,9 @@ export function getMenuList(pathname: string, t: any): Group[] {
icon: "mdi:chart-line",
submenus: [
{
href: "/admin/analysis/magement-content",
href: "/admin/analysis/content-management",
label: t("management-content"),
active: pathname === "/admin/analysis/magement-content",
active: pathname === "/admin/analysis/content-management",
icon: "",
children: [],
},
@ -1887,7 +1887,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
id: "feedback",
href: "/curator/feedback",
label: t("feedback"),
active: pathname.includes("/feedback"),
active: pathname.includes("/curator/feedback"),
icon: "mdi:feedback-outline",
submenus: [],
},

View File

@ -297,7 +297,7 @@
"colors": "Colors",
"performance-polda": "Performance Polda",
"analysis": "Analysis",
"management-content": "Management Content",
"management-content": "Content Management ",
"add-experts": "Add Experts"
},
"Changelog": {

View File

@ -297,7 +297,7 @@
"colors": "Colors",
"performance-polda": "Performa Polda",
"analysis": "Analisa",
"management-content": "Manajemen Konten",
"content-management": "Manajemen Konten",
"add-experts": "Tambah Tenaga Ahli"
},
"Changelog": {

View File

@ -45,6 +45,11 @@ const nextConfig = {
},
],
},
// eslint: {
// // Warning: This allows production builds to successfully complete even if
// // your project has ESLint errors.
// ignoreDuringBuilds: true,
// },
};
export default bundleAnalyzer(withNextIntl(withNextra(nextConfig)));

View File

@ -281,6 +281,9 @@ importers:
react-apexcharts:
specifier: ^1.4.1
version: 1.7.0(apexcharts@3.54.1)(react@18.3.1)
react-audio-voice-recorder:
specifier: ^2.2.0
version: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-chartjs-2:
specifier: ^5.2.0
version: 5.2.0(chart.js@4.4.7)(react@18.3.1)
@ -314,6 +317,9 @@ importers:
react-leaflet:
specifier: ^4.2.1
version: 4.2.1(leaflet@1.9.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-loading-skeleton:
specifier: ^3.5.0
version: 3.5.0(react@18.3.1)
react-player:
specifier: ^2.16.0
version: 2.16.0(react@18.3.1)
@ -338,6 +344,9 @@ importers:
react-time-picker:
specifier: ^7.0.0
version: 7.0.0(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-voice-recorder:
specifier: ^2.1.2
version: 2.1.2(react@18.3.1)
recharts:
specifier: ^2.12.7
version: 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -587,6 +596,10 @@ packages:
resolution: {integrity: sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'}
'@ffmpeg/ffmpeg@0.11.6':
resolution: {integrity: sha512-uN8J8KDjADEavPhNva6tYO9Fj0lWs9z82swF3YXnTxWMBoFLGq3LZ6FLlIldRKEzhOBKnkVfA8UnFJuvGvNxcA==}
engines: {node: '>=12.16.1'}
'@floating-ui/core@1.6.8':
resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==}
@ -3393,6 +3406,9 @@ packages:
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
engines: {node: '>= 0.4'}
is-url@1.2.4:
resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==}
is-weakmap@2.0.2:
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
engines: {node: '>= 0.4'}
@ -3961,6 +3977,15 @@ packages:
react: '>=16.13.1'
react-dom: '>=16.13.1'
node-fetch@2.7.0:
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
engines: {node: 4.x || >=6.0.0}
peerDependencies:
encoding: ^0.1.0
peerDependenciesMeta:
encoding:
optional: true
non-layered-tidy-tree-layout@2.0.2:
resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==}
@ -4233,6 +4258,18 @@ packages:
apexcharts: '>=4.0.0'
react: '>=0.13'
react-audio-visualize@1.2.0:
resolution: {integrity: sha512-rfO5nmT0fp23gjU0y2WQT6+ZOq2ZsuPTMphchwX1PCz1Di4oaIr6x7JZII8MLrbHdG7UB0OHfGONTIsWdh67kQ==}
peerDependencies:
react: '>=16.2.0'
react-dom: '>=16.2.0'
react-audio-voice-recorder@2.2.0:
resolution: {integrity: sha512-Hq+143Zs99vJojT/uFvtpxUuiIKoLbMhxhA7qgxe5v8hNXrh5/qTnvYP92hFaE5V+GyoCXlESONa0ufk7t5kHQ==}
peerDependencies:
react: '>=16.2.0'
react-dom: '>=16.2.0'
react-chartjs-2@5.2.0:
resolution: {integrity: sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==}
peerDependencies:
@ -4328,6 +4365,11 @@ packages:
react: ^18.0.0
react-dom: ^18.0.0
react-loading-skeleton@3.5.0:
resolution: {integrity: sha512-gxxSyLbrEAdXTKgfbpBEFZCO/P153DnqSCQau2+o6lNy1jgMRr2MmRmOzMmyrwSaSYLRB8g7b0waYPmUjz7IhQ==}
peerDependencies:
react: '>=16.8.0'
react-player@2.16.0:
resolution: {integrity: sha512-mAIPHfioD7yxO0GNYVFD1303QFtI3lyyQZLY229UEAp/a10cSW+hPcakg0Keq8uWJxT2OiT/4Gt+Lc9bD6bJmQ==}
peerDependencies:
@ -4423,6 +4465,12 @@ packages:
react: '>=16.6.0'
react-dom: '>=16.6.0'
react-voice-recorder@2.1.2:
resolution: {integrity: sha512-fjLN3fdVqsFrlISujAFAuVk85yCxhK4kcyyuahxa0fYo4LxyY36rGeQ4HCG8XRhfHrPxd5E632e//N5UqrnLKg==}
engines: {node: '>=10'}
peerDependencies:
react: ^16.0.0
react@16.14.0:
resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==}
engines: {node: '>=0.10.0'}
@ -4511,6 +4559,10 @@ packages:
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
resolve-url@0.2.1:
resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==}
deprecated: https://github.com/lydell/resolve-url#deprecated
resolve@1.22.10:
resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
engines: {node: '>= 0.4'}
@ -4897,6 +4949,9 @@ packages:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
@ -5132,11 +5187,17 @@ packages:
web-worker@1.3.0:
resolution: {integrity: sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==}
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
webpack-bundle-analyzer@4.10.1:
resolution: {integrity: sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==}
engines: {node: '>= 10.13.0'}
hasBin: true
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@ -5430,6 +5491,15 @@ snapshots:
'@faker-js/faker@8.4.1': {}
'@ffmpeg/ffmpeg@0.11.6':
dependencies:
is-url: 1.2.4
node-fetch: 2.7.0
regenerator-runtime: 0.13.11
resolve-url: 0.2.1
transitivePeerDependencies:
- encoding
'@floating-ui/core@1.6.8':
dependencies:
'@floating-ui/utils': 0.2.8
@ -8441,6 +8511,8 @@ snapshots:
dependencies:
which-typed-array: 1.1.18
is-url@1.2.4: {}
is-weakmap@2.0.2: {}
is-weakref@1.1.0:
@ -9309,6 +9381,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
node-fetch@2.7.0:
dependencies:
whatwg-url: 5.0.0
non-layered-tidy-tree-layout@2.0.2: {}
normalize-path@3.0.0: {}
@ -9579,6 +9655,20 @@ snapshots:
prop-types: 15.8.1
react: 18.3.1
react-audio-visualize@1.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-audio-voice-recorder@2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@ffmpeg/ffmpeg': 0.11.6
react: 18.3.1
react-audio-visualize: 1.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-dom: 18.3.1(react@18.3.1)
transitivePeerDependencies:
- encoding
react-chartjs-2@5.2.0(chart.js@4.4.7)(react@18.3.1):
dependencies:
chart.js: 4.4.7
@ -9670,6 +9760,10 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-loading-skeleton@3.5.0(react@18.3.1):
dependencies:
react: 18.3.1
react-player@2.16.0(react@18.3.1):
dependencies:
deepmerge: 4.3.1
@ -9796,6 +9890,10 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-voice-recorder@2.1.2(react@18.3.1):
dependencies:
react: 18.3.1
react@16.14.0:
dependencies:
loose-envify: 1.4.0
@ -9937,6 +10035,8 @@ snapshots:
resolve-pkg-maps@1.0.0: {}
resolve-url@0.2.1: {}
resolve@1.22.10:
dependencies:
is-core-module: 2.16.1
@ -10379,6 +10479,8 @@ snapshots:
totalist@3.0.1: {}
tr46@0.0.3: {}
trim-lines@3.0.1: {}
trough@2.2.0: {}
@ -10675,6 +10777,8 @@ snapshots:
web-worker@1.3.0: {}
webidl-conversions@3.0.1: {}
webpack-bundle-analyzer@4.10.1:
dependencies:
'@discoveryjs/json-ext': 0.5.7
@ -10694,6 +10798,11 @@ snapshots:
- bufferutil
- utf-8-validate
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
webidl-conversions: 3.0.1
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0