fix: logo polda and satker
This commit is contained in:
commit
444ddd6fcb
|
|
@ -40,19 +40,19 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
|
||||
{
|
||||
accessorKey: "name",
|
||||
accessorKey: "fullname",
|
||||
header: "Nama",
|
||||
cell: ({ row }) => <span>{row.getValue("name")}</span>,
|
||||
cell: ({ row }) => <span>{row.getValue("fullname")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "region",
|
||||
accessorKey: "address",
|
||||
header: "Wilayah",
|
||||
cell: ({ row }) => <span>{row.getValue("region")}</span>,
|
||||
cell: ({ row }) => <span>{row.getValue("address")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "skills",
|
||||
accessorKey: "role.name",
|
||||
header: "Bidang Keahlian",
|
||||
cell: ({ row }) => <span>{row.getValue("skills")}</span>,
|
||||
cell: ({ row }) => <span>{row.original.role?.name ?? "-"}</span>,
|
||||
},
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ import { listEnableCategory } from "@/service/content/content";
|
|||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { close, loading } from "@/config/swal";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { listDataExperts } from "@/service/experts/experts";
|
||||
|
||||
const dummyData = [
|
||||
{
|
||||
|
|
@ -93,6 +94,7 @@ const AddExpertTable = () => {
|
|||
const [statusFilter, setStatusFilter] = React.useState<number[]>([]);
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
@ -145,19 +147,44 @@ const AddExpertTable = () => {
|
|||
});
|
||||
}, [page, showData]);
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
loading();
|
||||
// async function fetchData() {
|
||||
// try {
|
||||
// loading();
|
||||
|
||||
const contentData = dummyData;
|
||||
// const contentData = dummyData;
|
||||
// contentData.forEach((item: any, index: number) => {
|
||||
// item.no = (page - 1) * Number(showData) + index + 1;
|
||||
// });
|
||||
|
||||
// setDataTable(contentData);
|
||||
// setTotalData(contentData?.length);
|
||||
// setTotalPage(1);
|
||||
// close();
|
||||
// } catch (error) {
|
||||
// console.error("Error fetching tasks:", error);
|
||||
// }
|
||||
// }
|
||||
|
||||
async function fetchData() {
|
||||
// const formattedStartDate = startDate
|
||||
// ? format(new Date(startDate), "yyyy-MM-dd")
|
||||
// : "";
|
||||
// const formattedEndDate = endDate
|
||||
// ? format(new Date(endDate), "yyyy-MM-dd")
|
||||
// : "";
|
||||
try {
|
||||
// const isForSelf = Number(roleId) === 4;
|
||||
const res = await listDataExperts(limit, page - 1);
|
||||
|
||||
const data = res?.data?.data;
|
||||
const contentData = data?.content;
|
||||
contentData.forEach((item: any, index: number) => {
|
||||
item.no = (page - 1) * Number(showData) + index + 1;
|
||||
item.no = (page - 1) * limit + index + 1;
|
||||
});
|
||||
|
||||
setDataTable(contentData);
|
||||
setTotalData(contentData?.length);
|
||||
setTotalPage(1);
|
||||
close();
|
||||
setTotalData(data?.totalElements);
|
||||
setTotalPage(data?.totalPages);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,27 +23,30 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { useEffect, useState } from "react";
|
||||
import { AdministrationLevelList, getListCompetencies, getListExperiences, saveUserInternal, saveUserRolePlacements } from "@/service/management-user/management-user";
|
||||
import { loading } from "@/config/swal";
|
||||
|
||||
const FormSchema = z.object({
|
||||
name: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
username: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
password: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
phoneNumber: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
email: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
position: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
region: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
skills: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
experience: z.string({
|
||||
experiences: z.string({
|
||||
required_error: "Required",
|
||||
}),
|
||||
company: z.string({
|
||||
|
|
@ -51,12 +54,34 @@ const FormSchema = z.object({
|
|||
}),
|
||||
});
|
||||
|
||||
export type Placements = {
|
||||
index: number;
|
||||
roleId?: string;
|
||||
userLevelId?: number;
|
||||
}
|
||||
|
||||
export default function AddExpertForm() {
|
||||
const MySwal = withReactContent(Swal);
|
||||
const router = useRouter();
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
});
|
||||
const [incrementId, setIncrementId] = useState(1);
|
||||
const [placementRows, setPlacementRows] = useState<Placements[]>([{ index: 0, roleId: "", userLevelId: 0 }]);
|
||||
const [userCompetencies, setUserCompetencies] = useState<any>();
|
||||
const [userExperiences, setUserExperiences] = useState<any>();
|
||||
const [userLevels, setUserLevels] = useState<any>();
|
||||
|
||||
const roleSelection = [
|
||||
{
|
||||
id: "11",
|
||||
name: "Koor Kurator",
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
name: "Kurator",
|
||||
}
|
||||
];
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||
MySwal.fire({
|
||||
|
|
@ -77,9 +102,85 @@ export default function AddExpertForm() {
|
|||
const save = async (data: z.infer<typeof FormSchema>) => {
|
||||
console.log("data", data);
|
||||
|
||||
// successSubmit();
|
||||
const dataReq = {
|
||||
firstName: data.name,
|
||||
username: data.username,
|
||||
email: data.email,
|
||||
password: data.password,
|
||||
adress: "",
|
||||
roleId: "EXP-ID",
|
||||
phoneNumber: data.phoneNumber,
|
||||
userCompetencyId: data.skills,
|
||||
userExperienceId: data.experiences,
|
||||
companyName: data.company,
|
||||
}
|
||||
|
||||
loading();
|
||||
const res = await saveUserInternal(dataReq);
|
||||
const resData = res?.data?.data;
|
||||
const userProfileId = resData.id;
|
||||
|
||||
var placementArr: any[] = [];
|
||||
placementRows.forEach((row: any) => {
|
||||
placementArr.push({
|
||||
roleId: Number(row.roleId),
|
||||
userLevelId: Number(row.userLevelId),
|
||||
userProfileId: userProfileId,
|
||||
});
|
||||
});
|
||||
|
||||
const dataReq2 = {
|
||||
userId: userProfileId,
|
||||
placements: placementArr
|
||||
}
|
||||
const res2 = await saveUserRolePlacements(dataReq2);
|
||||
const resData2 = res2?.data?.data;
|
||||
|
||||
success("/admin/add-experts");
|
||||
};
|
||||
|
||||
|
||||
function success(redirect: string): void {
|
||||
MySwal.fire({
|
||||
title: '<p class="text-green-600 font-bold">Sukses</p>',
|
||||
icon: "success",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: '<span class="text-white">OK</span>',
|
||||
allowOutsideClick: false,
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
router.push(redirect);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getDataAdditional();
|
||||
}, []);
|
||||
|
||||
async function getDataAdditional() {
|
||||
const resCompetencies = await getListCompetencies();
|
||||
setUserCompetencies(resCompetencies?.data?.data);
|
||||
|
||||
const resExperiences = await getListExperiences();
|
||||
setUserExperiences(resExperiences?.data?.data);
|
||||
|
||||
const resUserLevels = await AdministrationLevelList();
|
||||
const data = resUserLevels?.data?.data;
|
||||
var levelsArr: any[] = [];
|
||||
data.forEach((levels: any) => {
|
||||
levelsArr.push({
|
||||
id: levels.id,
|
||||
label: levels.name,
|
||||
name: levels.name,
|
||||
value: String(levels.id),
|
||||
levelNumber: levels.levelNumber,
|
||||
});
|
||||
});
|
||||
setUserLevels(levelsArr);
|
||||
}
|
||||
|
||||
|
||||
function successSubmit() {
|
||||
MySwal.fire({
|
||||
title: "Sukses",
|
||||
|
|
@ -92,6 +193,29 @@ export default function AddExpertForm() {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
const handleSelectionChange = (index: number, type: "roleId" | "userLevelId", value: string) => {
|
||||
setPlacementRows((prevRows) =>
|
||||
prevRows.map((row) =>
|
||||
row.index === index ? { ...row, [type]: value } : row
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const handleRemoveRow = (index: number) => {
|
||||
console.log(index);
|
||||
console.log(placementRows);
|
||||
const newPlacements = placementRows.filter((row) => row.index != index);
|
||||
console.log(newPlacements);
|
||||
setPlacementRows(newPlacements);
|
||||
};
|
||||
|
||||
const handleAddRow = () => {
|
||||
setPlacementRows((prevRows: any) => [...prevRows, { index: incrementId, roleId: "", userLevelId: 0 }]);
|
||||
setIncrementId((prevId) => prevId + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
|
|
@ -118,6 +242,22 @@ export default function AddExpertForm() {
|
|||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="username"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<Input
|
||||
value={field.value}
|
||||
placeholder="Masukkan Username"
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="phoneNumber"
|
||||
|
|
@ -152,45 +292,16 @@ export default function AddExpertForm() {
|
|||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="position"
|
||||
name="password"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Posisi</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Pilih Region" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="koor-kurator">Koor Kurator</SelectItem>
|
||||
<SelectItem value="kurator">Kurator</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
<FormLabel>Password</FormLabel>
|
||||
<Input
|
||||
type="password"
|
||||
value={field.value}
|
||||
placeholder="Masukkan Password"
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Wilayah</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Pilih Region" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="nasional">Nasional</SelectItem>
|
||||
<SelectItem value="jakarta">DKI Jakarta</SelectItem>
|
||||
<SelectItem value="jabar">Jawa Barat</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
|
|
@ -208,19 +319,20 @@ export default function AddExpertForm() {
|
|||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="komunikasi">Komunikasi</SelectItem>
|
||||
<SelectItem value="hukum">Hukum</SelectItem>
|
||||
<SelectItem value="bahasa">Bahasa</SelectItem>
|
||||
{userCompetencies?.map((item: any) => (
|
||||
<SelectItem key={item.id} value={String(item.id)}>
|
||||
{item.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="experience"
|
||||
name="experiences"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Pengalaman</FormLabel>
|
||||
|
|
@ -231,15 +343,13 @@ export default function AddExpertForm() {
|
|||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="akademisi">Akademisi</SelectItem>
|
||||
<SelectItem value="praktisi">Praktisi</SelectItem>
|
||||
<SelectItem value="akademisi+praktisi">
|
||||
Akademisi + Praktisi
|
||||
{userExperiences?.map((item: any) => (
|
||||
<SelectItem key={item.id} value={String(item.id)}>
|
||||
{item.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
|
@ -261,6 +371,59 @@ export default function AddExpertForm() {
|
|||
)}
|
||||
/>
|
||||
|
||||
<div className="mt-4">
|
||||
<FormLabel>Penempatan</FormLabel>
|
||||
{placementRows?.map((row: any) => (
|
||||
<div key={row.index} className="flex items-center gap-2 my-2">
|
||||
<Select onValueChange={(e) => handleSelectionChange(row.index, "roleId", e)} >
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Pilih Role" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{roleSelection?.map((item: any) => (
|
||||
<SelectItem key={item.id} value={String(item.id)}>
|
||||
{item.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select onValueChange={(e) => handleSelectionChange(row.index, "userLevelId", e)}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Pilih User Level" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{userLevels?.map((item: any) => (
|
||||
<SelectItem key={item.id} value={String(item.id)}>
|
||||
{item.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{placementRows.length > 1 && (
|
||||
<Button
|
||||
type="button"
|
||||
size="md"
|
||||
color="destructive"
|
||||
onClick={() => handleRemoveRow(row.index)}
|
||||
>
|
||||
Hapus
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<Button
|
||||
type="button"
|
||||
size="md"
|
||||
onClick={() => handleAddRow()}
|
||||
>
|
||||
Tambah
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row justify-end gap-2 mt-4 pt-4">
|
||||
<Button
|
||||
size="md"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export default function PerformancePolda() {
|
|||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<p className="font-semibold">PERFORMANCE KUMULATIF PER POLDA</p>
|
||||
<p className="font-semibold">PERFORMANCE KUMULATIF PER POLRES</p>
|
||||
<PerformancePolresViz />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import PerformancePolresViz from "@/components/visualization/performance-polres";
|
||||
import PerformanceSatkerViz from "@/components/visualization/performance-satker";
|
||||
|
||||
export default function PerformanceSatker() {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<p className="font-semibold">PERFORMANCE KUMULATIF PER SATKER</p>
|
||||
<PerformanceSatkerViz />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -14,9 +14,7 @@ export default function AdminBanner() {
|
|||
<SiteBreadcrumb />
|
||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||
<div className="flex justify-between">
|
||||
{selectedTab === "content"
|
||||
? "Daftar List Media"
|
||||
: "Table List Banner"}
|
||||
{selectedTab === "content" ? "List Media" : " List Banner"}
|
||||
|
||||
<div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-5">
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import Image from "next/image";
|
|||
import { Upload } from "tus-js-client";
|
||||
import { getCookiesDecrypt } from "@/lib/utils";
|
||||
import Cookies from "js-cookie";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const FormSchema = z.object({
|
||||
title: z.string({
|
||||
|
|
@ -109,7 +110,7 @@ export default function CreateCategoryModal() {
|
|||
const levelNumber = getCookiesDecrypt("ulne");
|
||||
const userLevelId = getCookiesDecrypt("ulie");
|
||||
const poldaState = Cookies.get("state");
|
||||
|
||||
const t = useTranslations("Menu");
|
||||
const [files, setFiles] = useState<File[]>([]);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [satkerData, setSatkerData] = useState<string[]>([]);
|
||||
|
|
@ -239,12 +240,12 @@ export default function CreateCategoryModal() {
|
|||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button color="primary" size="md">
|
||||
Tambah Kategori
|
||||
{t("add-category")}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent size="md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Tambah Kategori</DialogTitle>
|
||||
<DialogTitle> {t("add-category")}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ import {
|
|||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import CreateCategoryModal from "./create";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const AdminCategoryTable = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const t = useTranslations("Menu");
|
||||
const dataChange = searchParams?.get("dataChange");
|
||||
const [openModal, setOpenModal] = React.useState(false);
|
||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||
|
|
@ -127,7 +129,7 @@ const AdminCategoryTable = () => {
|
|||
return (
|
||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||
<div className="flex justify-between mb-10 items-center">
|
||||
<p className="text-xl font-medium text-default-900">Kategori</p>
|
||||
<p className="text-xl font-medium text-default-900">{t("category")}</p>
|
||||
<CreateCategoryModal />
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import { useDropzone } from "react-dropzone";
|
|||
import { CloudUpload } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { Upload } from "tus-js-client";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const FormSchema = z.object({
|
||||
answer: z.string({
|
||||
|
|
@ -79,7 +80,7 @@ const publishToList = [
|
|||
export default function CreateFAQModal() {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
const t = useTranslations("Menu");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [satkerData, setSatkerData] = useState<string[]>([]);
|
||||
const [unitData, setUnitData] = useState<string[]>([]);
|
||||
|
|
@ -120,12 +121,12 @@ export default function CreateFAQModal() {
|
|||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button color="primary" size="md">
|
||||
Tambah FAQ
|
||||
{t("add")} FAQ
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent size="md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Tambah FAQ</DialogTitle>
|
||||
<DialogTitle>{t("add")} FAQ</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import { useDropzone } from "react-dropzone";
|
|||
import { CloudUpload } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { Upload } from "tus-js-client";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const FormSchema = z.object({
|
||||
question: z.string({
|
||||
|
|
@ -77,7 +78,7 @@ const publishToList = [
|
|||
export default function CreateFAQModal() {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
const t = useTranslations("Menu");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
|
|
@ -110,12 +111,12 @@ export default function CreateFAQModal() {
|
|||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button color="primary" size="md">
|
||||
Tambah Feedback
|
||||
{t("add")} Feedback
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent size="md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Tambah Feedback</DialogTitle>
|
||||
<DialogTitle>{t("add")} Feedback</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
|
|
|
|||
|
|
@ -41,11 +41,13 @@ import {
|
|||
} from "@/service/settings/settings";
|
||||
|
||||
import CreateFAQModal from "./create";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const AdminFeedbackTable = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const dataChange = searchParams?.get("dataChange");
|
||||
|
||||
const [openModal, setOpenModal] = React.useState(false);
|
||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||
const [totalData, setTotalData] = React.useState<number>(1);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import {
|
|||
CommandList,
|
||||
} from "@/components/ui/command";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const FormSchema = z.object({
|
||||
name: z.string({
|
||||
|
|
@ -55,6 +56,7 @@ const FormSchema = z.object({
|
|||
export default function CreateTagModal() {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const t = useTranslations("Menu");
|
||||
const [categoryList, setCategoryList] = useState<
|
||||
{ id: number; label: string; value: string }[]
|
||||
>([]);
|
||||
|
|
@ -107,12 +109,12 @@ export default function CreateTagModal() {
|
|||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button color="primary" size="md">
|
||||
Tambah Tag
|
||||
{t("add-tags")}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent size="md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Tambah Tag</DialogTitle>
|
||||
<DialogTitle> {t("add-tags")}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form
|
||||
|
|
|
|||
|
|
@ -42,10 +42,12 @@ import {
|
|||
} from "@/service/settings/settings";
|
||||
|
||||
import CreateFAQModal from "./create";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const AdminTagTable = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const t = useTranslations("Menu");
|
||||
const dataChange = searchParams?.get("dataChange");
|
||||
const [openModal, setOpenModal] = React.useState(false);
|
||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||
|
|
@ -124,7 +126,7 @@ const AdminTagTable = () => {
|
|||
return (
|
||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||
<div className="flex justify-between mb-10 items-center">
|
||||
<p className="text-xl font-medium text-default-900">Tag</p>
|
||||
<p className="text-xl font-medium text-default-900">{t("tags")}</p>
|
||||
<CreateFAQModal />
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,9 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
|||
);
|
||||
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
|
||||
const roleId = Number(getCookiesDecrypt("urie")) || 0;
|
||||
const userLevelId = Number(getCookiesDecrypt("ulie")) || 0;
|
||||
console.log("roleId", roleId);
|
||||
console.log("userlevel", userLevelId);
|
||||
const [apiEvents, setApiEvents] = useState<CalendarEvent[]>([]);
|
||||
const [Isloading, setLoading] = useState<boolean>(false);
|
||||
const [draggableInitialized, setDraggableInitialized] =
|
||||
|
|
@ -574,11 +577,11 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
|||
<div className="grid grid-cols-12 gap-6 divide-x divide-border">
|
||||
<Card className="col-span-12 lg:col-span-4 2xl:col-span-3 pb-5">
|
||||
<CardContent className="p-0">
|
||||
<CardHeader className="border-none mb-2 pt-5">
|
||||
<CardHeader className="border-none mb-2 pt-5 ">
|
||||
{roleId == 3 || roleId == 11 || roleId == 2 || roleId == 12 ? (
|
||||
<Button
|
||||
onClick={handleDateClick}
|
||||
className="dark:bg-background dark:text-foreground"
|
||||
className="dark:bg-background dark:text-foreground w-[250px]"
|
||||
>
|
||||
<Plus className="w-4 h-4 me-1" />
|
||||
{t("addEvent")}
|
||||
|
|
@ -589,8 +592,8 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
|||
<div>
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
{roleId == 2 ? (
|
||||
<Button className="dark:bg-background dark:text-foreground ">
|
||||
{roleId === 3 && userLevelId === 216 ? (
|
||||
<Button className="dark:bg-background dark:text-foreground w-[250px]">
|
||||
<Book className="w-4 h-4" />
|
||||
{t("bag-pa-monitoring-results")}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import { listEnableCategory } from "@/service/content/content";
|
|||
import { useTranslations } from "next-intl";
|
||||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const BlogTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -73,7 +74,7 @@ const BlogTable = () => {
|
|||
);
|
||||
const [categoryFilter, setCategoryFilter] = React.useState<string>("");
|
||||
const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -17,28 +17,32 @@ import Swal from "sweetalert2";
|
|||
import withReactContent from "sweetalert2-react-content";
|
||||
import { deleteBlog } from "@/service/blog/blog";
|
||||
import { error, loading } from "@/lib/swal";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-normal">{row.getValue("title")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Category",
|
||||
header: t("category"),
|
||||
cell: ({ row }) => <span>{row.getValue("categoryName")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Upload Date",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -54,7 +58,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag",
|
||||
header: t("tag"),
|
||||
cell: ({ row }) => <span className="">{row.getValue("tags")}</span>,
|
||||
},
|
||||
{
|
||||
|
|
@ -85,7 +89,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const router = useRouter();
|
||||
|
|
@ -166,6 +170,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@ import withReactContent from "sweetalert2-react-content";
|
|||
import { deleteMedia } from "@/service/content/content";
|
||||
import { error } from "@/lib/swal";
|
||||
import Swal from "sweetalert2";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const MySwal = withReactContent(Swal);
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -34,7 +38,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -46,14 +50,16 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Category Name",
|
||||
header: t("category-name"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("categoryName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Upload Date",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -69,14 +75,14 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "creatorName",
|
||||
header: "Creator Group",
|
||||
header: t("creator-group"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "creatorGroupLevelName",
|
||||
header: "Sumber",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("creatorGroupLevelName")}
|
||||
|
|
@ -85,7 +91,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "publishedOn",
|
||||
header: "Published",
|
||||
header: t("published"),
|
||||
cell: ({ row }) => {
|
||||
const isPublish = row.original.isPublish;
|
||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||
|
|
@ -138,7 +144,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
|
@ -198,13 +204,17 @@ const columns: ColumnDef<any>[] = [
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<Link href={`/contributor/content/audio/detail/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/audio/detail/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
<Link href={`/contributor/content/audio/update/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/audio/update/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
|
|
@ -222,6 +232,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ import {
|
|||
} from "@/service/content/content";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { format } from "date-fns";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const TableAudio = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -99,7 +100,7 @@ const TableAudio = () => {
|
|||
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
"use client";
|
||||
import * as React from "react";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
|
|
@ -19,13 +20,15 @@ import { deleteMedia } from "@/service/content/content";
|
|||
import { error, loading } from "@/lib/swal";
|
||||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const MySwal = withReactContent(Swal);
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -38,7 +41,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -50,14 +53,16 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Category Name",
|
||||
header: t("category-name"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("categoryName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Upload Date",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -73,14 +78,14 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "creatorName",
|
||||
header: "Creator Group",
|
||||
header: t("creator-group"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "creatorGroupLevelName",
|
||||
header: "Sumber",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("creatorGroupLevelName")}
|
||||
|
|
@ -89,7 +94,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "publishedOn",
|
||||
header: "Published",
|
||||
header: t("published"),
|
||||
cell: ({ row }) => {
|
||||
const isPublish = row.original.isPublish;
|
||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||
|
|
@ -110,53 +115,29 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
//
|
||||
{
|
||||
accessorKey: "statusId",
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
const userLevelId = 2; // Gantilah sesuai dengan konteks aplikasi
|
||||
const statusId = Number(row.getValue("statusId"));
|
||||
const reviewedAtLevel = row.original.reviewedAtLevel as string | null;
|
||||
const needApprovalFromLevel = Number(row.original.needApprovalFromLevel);
|
||||
const statusColors: Record<string, string> = {
|
||||
diterima: "bg-green-100 text-green-600",
|
||||
"menunggu review": "bg-orange-100 text-orange-600",
|
||||
};
|
||||
|
||||
let statusName = row.getValue("statusName") as string;
|
||||
let icon = "fa:times-circle";
|
||||
let statusClass = "bg-gray-100 text-gray-600";
|
||||
|
||||
if (
|
||||
(statusId === 2 &&
|
||||
reviewedAtLevel !== null &&
|
||||
!reviewedAtLevel.includes(`:${userLevelId}:`)) ||
|
||||
(statusId === 1 && needApprovalFromLevel === userLevelId)
|
||||
) {
|
||||
statusName = "Menunggu Review";
|
||||
icon = "fa:hourglass-end";
|
||||
statusClass = "bg-orange-100 text-orange-600";
|
||||
} else if (
|
||||
statusId === 2 &&
|
||||
reviewedAtLevel?.includes(`:${userLevelId}:`)
|
||||
) {
|
||||
icon = "fa:check-circle";
|
||||
statusClass = "bg-green-100 text-green-600";
|
||||
} else if (statusId === 2) {
|
||||
icon = "fa:check-circle";
|
||||
statusClass = "bg-green-100 text-green-600";
|
||||
} else if (statusId === 3) {
|
||||
icon = "fa:comment";
|
||||
statusClass = "bg-blue-100 text-blue-600";
|
||||
} else if (statusId === 1) {
|
||||
icon = "fa:hourglass-end";
|
||||
statusClass = "bg-orange-100 text-orange-600";
|
||||
}
|
||||
const status = row.getValue("statusName") as string;
|
||||
const statusName = status?.toLocaleLowerCase();
|
||||
const statusStyles =
|
||||
statusColors[statusName] || "bg-red-200 text-red-600";
|
||||
|
||||
return (
|
||||
<Badge
|
||||
className={cn(
|
||||
"rounded-full px-5 w-full whitespace-nowrap",
|
||||
statusClass
|
||||
statusStyles
|
||||
)}
|
||||
>
|
||||
{statusName}
|
||||
{status} {/* Tetap tampilkan nilai asli */}
|
||||
</Badge>
|
||||
);
|
||||
},
|
||||
|
|
@ -165,7 +146,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const router = useRouter();
|
||||
|
|
@ -226,13 +207,17 @@ const columns: ColumnDef<any>[] = [
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<Link href={`/contributor/content/image/detail/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/image/detail/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
<Link href={`/contributor/content/image/update/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/image/update/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
|
|
@ -250,6 +235,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ import { ticketingPagination } from "@/service/ticketing/ticketing";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import TablePagination from "@/components/table/table-pagination";
|
||||
import columns from "./columns";
|
||||
|
||||
import {
|
||||
deleteMedia,
|
||||
listDataImage,
|
||||
|
|
@ -66,6 +66,7 @@ import withReactContent from "sweetalert2-react-content";
|
|||
import { error } from "@/lib/swal";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { format } from "date-fns";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const TableImage = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -104,7 +105,7 @@ const TableImage = () => {
|
|||
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -16,11 +16,17 @@ import {
|
|||
} from "@/components/ui/dropdown-menu";
|
||||
import { format } from "date-fns";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const MySwal = withReactContent(Swal);
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -33,7 +39,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "contentTitle",
|
||||
header: "Judul",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("contentTitle");
|
||||
return (
|
||||
|
|
@ -45,7 +51,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "contentTag",
|
||||
header: "Tag",
|
||||
header: t("tag"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("contentTag")}</span>
|
||||
),
|
||||
|
|
@ -53,14 +59,14 @@ const columns: ColumnDef<any>[] = [
|
|||
|
||||
{
|
||||
accessorKey: "contentType",
|
||||
header: "Tipe Konten ",
|
||||
header: t("type-content"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("contentType")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "contentCreatedGroupBy",
|
||||
header: "Sumber ",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("contentCreatedGroupBy")}
|
||||
|
|
@ -92,7 +98,7 @@ const columns: ColumnDef<any>[] = [
|
|||
|
||||
{
|
||||
accessorKey: "contentCreatedDate",
|
||||
header: "Tanggal Unggah",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("contentCreatedDate") as
|
||||
| string
|
||||
|
|
@ -147,6 +153,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ import {
|
|||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { format } from "date-fns";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
// export type CompanyData = {
|
||||
// no: number;
|
||||
|
|
@ -77,7 +80,8 @@ const TableSPIT = () => {
|
|||
const [search, setSearch] = React.useState("");
|
||||
const userId = getCookiesDecrypt("uie");
|
||||
const userLevelId = getCookiesDecrypt("ulie");
|
||||
|
||||
const t = useTranslations("AnalyticsDashboard");
|
||||
const [dateFilter, setDateFilter] = React.useState("");
|
||||
const [totalData, setTotalData] = React.useState<number>(1);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
|
|
@ -86,7 +90,7 @@ const TableSPIT = () => {
|
|||
const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: spitTable,
|
||||
columns,
|
||||
|
|
@ -117,7 +121,7 @@ const TableSPIT = () => {
|
|||
|
||||
React.useEffect(() => {
|
||||
fetchData();
|
||||
}, [page, limit, search, statusFilter]);
|
||||
}, [page, limit, search, statusFilter, dateFilter]);
|
||||
|
||||
async function fetchData() {
|
||||
let isPublish;
|
||||
|
|
@ -129,8 +133,18 @@ const TableSPIT = () => {
|
|||
isPublish = statusFilter.includes(1) ? false : true;
|
||||
}
|
||||
|
||||
const formattedStartDate = dateFilter
|
||||
? format(new Date(dateFilter), "yyyy-MM-dd")
|
||||
: "";
|
||||
|
||||
try {
|
||||
const res = await listSPIT(page - 1, limit, search, isPublish);
|
||||
const res = await listSPIT(
|
||||
page - 1,
|
||||
limit,
|
||||
search,
|
||||
formattedStartDate,
|
||||
isPublish
|
||||
);
|
||||
const data = res?.data?.data;
|
||||
const contentData = data?.content || [];
|
||||
|
||||
|
|
@ -192,6 +206,15 @@ const TableSPIT = () => {
|
|||
<div className="flex flex-row justify-between my-1 mx-1">
|
||||
<p>Filter</p>
|
||||
</div>
|
||||
<div className="mx-2 my-1">
|
||||
<Label>{t("date")}</Label>
|
||||
<Input
|
||||
type="date"
|
||||
value={dateFilter}
|
||||
onChange={(e) => setDateFilter(e.target.value)}
|
||||
className="max-w-sm"
|
||||
/>
|
||||
</div>
|
||||
<Label className="ml-2 mt-2">Status</Label>
|
||||
<div className="flex items-center px-4 py-1">
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@ import { error } from "@/lib/swal";
|
|||
import { deleteMedia } from "@/service/content/content";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import Swal from "sweetalert2";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const MySwal = withReactContent(Swal);
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -34,7 +38,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -46,14 +50,16 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Category Name",
|
||||
header: t("category-name"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("categoryName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Upload Date",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -69,14 +75,14 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "creatorName",
|
||||
header: "Creator Group",
|
||||
header: t("creator-group"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "creatorGroupLevelName",
|
||||
header: "Sumber",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("creatorGroupLevelName")}
|
||||
|
|
@ -85,7 +91,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "publishedOn",
|
||||
header: "Published",
|
||||
header: t("published"),
|
||||
cell: ({ row }) => {
|
||||
const isPublish = row.original.isPublish;
|
||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||
|
|
@ -139,7 +145,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
|
@ -199,13 +205,17 @@ const columns: ColumnDef<any>[] = [
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<Link href={`/contributor/content/teks/detail/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/teks/detail/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
<Link href={`/contributor/content/teks/update/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/teks/update/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
|
|
@ -223,6 +233,8 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default columns;
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import {
|
|||
} from "@/service/content/content";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { format } from "date-fns";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const TableTeks = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -98,7 +99,7 @@ const TableTeks = () => {
|
|||
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@ import { deleteMedia } from "@/service/content/content";
|
|||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import { error } from "@/lib/swal";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -34,7 +39,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -46,14 +51,16 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Category Name",
|
||||
header: t("category-name"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("categoryName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Upload Date",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -69,14 +76,14 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "creatorName",
|
||||
header: "Creator Group",
|
||||
header: t("creator-group"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "creatorGroupLevelName",
|
||||
header: "Sumber",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("creatorGroupLevelName")}
|
||||
|
|
@ -85,7 +92,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "publishedOn",
|
||||
header: "Published",
|
||||
header: t("published"),
|
||||
cell: ({ row }) => {
|
||||
const isPublish = row.original.isPublish;
|
||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||
|
|
@ -136,7 +143,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
|
@ -196,13 +203,17 @@ const columns: ColumnDef<any>[] = [
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<Link href={`/contributor/content/video/detail/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/video/detail/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
<Link href={`/contributor/content/video/update/${row.original.id}`}>
|
||||
<Link
|
||||
href={`/contributor/content/video/update/${row.original.id}`}
|
||||
>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
|
|
@ -220,6 +231,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import {
|
|||
} from "@/service/content/content";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { format } from "date-fns";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const TableVideo = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -98,7 +99,7 @@ const TableVideo = () => {
|
|||
const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { format } from "date-fns";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -30,7 +33,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
header: t("title"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -43,7 +46,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -77,7 +80,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -112,6 +115,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import { getPlanningSentPagination } from "@/service/planning/planning";
|
|||
import search from "@/app/[locale]/(protected)/app/chat/components/search";
|
||||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { useTranslations } from "next-intl";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const MediahubTable = () => {
|
||||
const t = useTranslations("Planning");
|
||||
|
|
@ -78,7 +79,7 @@ const MediahubTable = () => {
|
|||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { format } from "date-fns";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -30,7 +33,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
header: t("title"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -43,7 +46,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -77,7 +80,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -110,6 +113,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import columns from "./columns";
|
|||
import { getPlanningSentPagination } from "@/service/planning/planning";
|
||||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { useTranslations } from "next-intl";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const MedsosTable = () => {
|
||||
const t = useTranslations("Planning");
|
||||
|
|
@ -77,7 +78,7 @@ const MedsosTable = () => {
|
|||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,15 @@ import {
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -30,7 +34,7 @@ const columns: ColumnDef<any>[] = [
|
|||
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -42,21 +46,21 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "startDate",
|
||||
header: "Start Date ",
|
||||
header: t("start-date"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "endDate",
|
||||
header: "End Date",
|
||||
header: t("end-date"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "time",
|
||||
header: "Time",
|
||||
header: t("time"),
|
||||
cell: ({ row }: { row: { original: any } }) => {
|
||||
console.log("Row Original Data:", row.original);
|
||||
const { startTime, endTime } = row.original;
|
||||
|
|
@ -69,7 +73,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "address",
|
||||
header: "Address",
|
||||
header: t("address"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const address: string = row.getValue("address");
|
||||
return (
|
||||
|
|
@ -107,7 +111,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "speaker",
|
||||
header: "Disampaikan oleh",
|
||||
header: t("speaker"),
|
||||
cell: ({ row }: { row: { original: any } }) => {
|
||||
console.log("Row Original Data:", row.original);
|
||||
const { speakerTitle, speakerName } = row.original;
|
||||
|
|
@ -120,16 +124,18 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "uploaderName",
|
||||
header: "Sumber ",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("uploaderName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("uploaderName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -169,6 +175,8 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default columns;
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import { useTranslations } from "next-intl";
|
|||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const EventTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -55,7 +56,7 @@ const EventTable = () => {
|
|||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,15 @@ import {
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -30,7 +34,7 @@ const columns: ColumnDef<any>[] = [
|
|||
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -42,21 +46,21 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "startDate",
|
||||
header: "Start Date ",
|
||||
header: t("start-date"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "endDate",
|
||||
header: "End Date",
|
||||
header: t("end-date"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "time",
|
||||
header: "Time",
|
||||
header: t("time"),
|
||||
cell: ({ row }: { row: { original: any } }) => {
|
||||
console.log("Row Original Data:", row.original);
|
||||
const { startTime, endTime } = row.original;
|
||||
|
|
@ -69,7 +73,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "address",
|
||||
header: "Address",
|
||||
header: t("address"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const address: string = row.getValue("address");
|
||||
return (
|
||||
|
|
@ -107,7 +111,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "speaker",
|
||||
header: "Disampaikan oleh",
|
||||
header: t("speaker"),
|
||||
cell: ({ row }: { row: { original: any } }) => {
|
||||
console.log("Row Original Data:", row.original);
|
||||
const { speakerTitle, speakerName } = row.original;
|
||||
|
|
@ -120,16 +124,18 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "uploaderName",
|
||||
header: "Sumber ",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("uploaderName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("uploaderName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -169,6 +175,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import { paginationSchedule } from "@/service/schedule/schedule";
|
|||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { useTranslations } from "next-intl";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const PressConferenceTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -68,7 +69,7 @@ const PressConferenceTable = () => {
|
|||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -12,11 +12,15 @@ import {
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -30,7 +34,7 @@ const columns: ColumnDef<any>[] = [
|
|||
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const title: string = row.getValue("title");
|
||||
return (
|
||||
|
|
@ -42,21 +46,21 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "startDate",
|
||||
header: "Start Date ",
|
||||
header: t("start-date"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("startDate")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "endDate",
|
||||
header: "End Date",
|
||||
header: t("end-date"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("endDate")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "time",
|
||||
header: "Time",
|
||||
header: t("time"),
|
||||
cell: ({ row }: { row: { original: any } }) => {
|
||||
console.log("Row Original Data:", row.original);
|
||||
const { startTime, endTime } = row.original;
|
||||
|
|
@ -69,7 +73,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "address",
|
||||
header: "Address",
|
||||
header: t("address"),
|
||||
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
|
||||
const address: string = row.getValue("address");
|
||||
return (
|
||||
|
|
@ -107,7 +111,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "speaker",
|
||||
header: "Disampaikan oleh",
|
||||
header: t("speaker"),
|
||||
cell: ({ row }: { row: { original: any } }) => {
|
||||
console.log("Row Original Data:", row.original);
|
||||
const { speakerTitle, speakerName } = row.original;
|
||||
|
|
@ -120,16 +124,18 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "uploaderName",
|
||||
header: "Sumber ",
|
||||
header: t("source"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("uploaderName")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("uploaderName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -169,6 +175,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import { paginationSchedule } from "@/service/schedule/schedule";
|
|||
import { useTranslations } from "next-intl";
|
||||
import { CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const PressReleaseTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -69,7 +70,7 @@ const PressReleaseTable = () => {
|
|||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -20,16 +20,19 @@ import { deleteTask } from "@/service/task";
|
|||
import { error, loading } from "@/lib/swal";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import Swal from "sweetalert2";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
header: t("title"),
|
||||
cell: ({ row }) => (
|
||||
<div>
|
||||
<span>{row.getValue("title")}</span>
|
||||
|
|
@ -49,13 +52,13 @@ const columns: ColumnDef<any>[] = [
|
|||
|
||||
{
|
||||
accessorKey: "uniqueCode",
|
||||
header: "Code",
|
||||
header: t("code"),
|
||||
cell: ({ row }) => <span>{row.getValue("uniqueCode")}</span>,
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "assignmentMainType",
|
||||
header: "Type Task",
|
||||
header: t("type-task"),
|
||||
cell: ({ row }) => {
|
||||
const type = row.getValue("assignmentMainType") as { name: string };
|
||||
return <span>{type?.name}</span>;
|
||||
|
|
@ -63,7 +66,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "assignmentType",
|
||||
header: "Category Task",
|
||||
header: t("category-task"),
|
||||
cell: ({ row }) => {
|
||||
const type = row.getValue("assignmentType") as { name: string };
|
||||
return <span>{type?.name}</span>;
|
||||
|
|
@ -71,7 +74,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Upload Date ",
|
||||
header: t("upload-date"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -119,7 +122,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const router = useRouter();
|
||||
|
|
@ -201,6 +204,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import { listTask } from "@/service/task";
|
|||
import { Label } from "@/components/ui/label";
|
||||
import { format } from "date-fns";
|
||||
import { useTranslations } from "next-intl";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const TaskTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -83,7 +84,7 @@ const TaskTable = () => {
|
|||
const [limit, setLimit] = React.useState(10);
|
||||
const [isSpecificAttention, setIsSpecificAttention] = React.useState(true);
|
||||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -181,16 +181,16 @@ export default function ExecutiveDashboard() {
|
|||
const view2 =
|
||||
levelName == "MABES POLRI"
|
||||
? isInternational[1]
|
||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-publisher?"
|
||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-konten-publisher?"
|
||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-konten-publisher-polda?provinsi-polda=${poldaState}&`;
|
||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-published-produksi?"
|
||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev202/db-published-produksi-executive?"
|
||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev202/db-konten-publisher-polda-executive?provinsi-polda=${poldaState}&`;
|
||||
|
||||
const view3 =
|
||||
levelName == "MABES POLRI"
|
||||
? isInternational[2]
|
||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-waktu-akses-pengguna?"
|
||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-waktu-akses-pengguna?"
|
||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-waktu-akses-pengguna-polda?provinsi-polda=${poldaState}&`;
|
||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev202/db-waktu-akses-pengguna-executive?"
|
||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev202/db-waktu-akses-pengguna-polda-executive?provinsi-polda=${poldaState}&`;
|
||||
|
||||
const view4 =
|
||||
levelName == "MABES POLRI"
|
||||
|
|
@ -212,6 +212,21 @@ export default function ExecutiveDashboard() {
|
|||
async function initState() {
|
||||
const response1 = await generateTicket();
|
||||
setTicket1(response1?.data?.data);
|
||||
|
||||
const response2 = await generateTicket();
|
||||
setTicket2(response2?.data?.data);
|
||||
|
||||
const response3 = await generateTicket();
|
||||
setTicket3(response3?.data?.data);
|
||||
|
||||
const response4 = await generateTicket();
|
||||
setTicket4(response4?.data?.data);
|
||||
|
||||
const response5 = await generateTicket();
|
||||
setTicket5(response5?.data?.data);
|
||||
|
||||
const response6 = await generateTicket();
|
||||
setTicket6(response6?.data?.data);
|
||||
}
|
||||
|
||||
initState();
|
||||
|
|
@ -235,35 +250,6 @@ export default function ExecutiveDashboard() {
|
|||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Download Report</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Download Report</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="w-full">
|
||||
<Label>Date</Label>
|
||||
<Input
|
||||
type="date"
|
||||
// value={dateFilter}
|
||||
// onChange={(e) => setDateFilter(e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="submit"
|
||||
// onClick={downloadReport}
|
||||
>
|
||||
Download
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<div className="mt-3 flex flex-row gap-3 justify-center">
|
||||
<Card className="rounded-sm w-4/12 p-3">
|
||||
<div className="flex flex-row justify-between">
|
||||
|
|
@ -298,7 +284,7 @@ export default function ExecutiveDashboard() {
|
|||
<LucideBoxSelect />
|
||||
</div>
|
||||
<div className="my-5">
|
||||
{ticket1 == "" ? (
|
||||
{ticket2 == "" ? (
|
||||
<iframe
|
||||
src={`${baseUrl + view4 + param}`}
|
||||
width="100%"
|
||||
|
|
@ -307,7 +293,7 @@ export default function ExecutiveDashboard() {
|
|||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${`${url + ticket1}/${view4}${param}`}`}
|
||||
src={`${`${url + ticket2}/${view4}${param}`}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
frameBorder="0"
|
||||
|
|
@ -323,7 +309,7 @@ export default function ExecutiveDashboard() {
|
|||
<LucideBoxSelect />
|
||||
</div>
|
||||
<div className="my-5">
|
||||
{ticket1 == "" ? (
|
||||
{ticket3 == "" ? (
|
||||
<iframe
|
||||
src={`${baseUrl + view5 + param}`}
|
||||
width="100%"
|
||||
|
|
@ -332,7 +318,7 @@ export default function ExecutiveDashboard() {
|
|||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${`${url + ticket1}/${view5}${param}`}`}
|
||||
src={`${`${url + ticket3}/${view5}${param}`}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
frameBorder="0"
|
||||
|
|
@ -342,24 +328,24 @@ export default function ExecutiveDashboard() {
|
|||
</Card>
|
||||
</div>
|
||||
<div className="w-full mt-3">
|
||||
<Card className="rounded-sm p-3 h-[850px]">
|
||||
<Card className="rounded-sm p-3 h-[750px]">
|
||||
<div className="flex flex-row justify-between">
|
||||
<p className="text-base font-semibold">Konten Paling Populer</p>
|
||||
<LucideBoxSelect />
|
||||
</div>
|
||||
<div className="my-5">
|
||||
{ticket2 == "" ? (
|
||||
{ticket4 == "" ? (
|
||||
<iframe
|
||||
src={`${baseUrl + view2 + param}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
height="650"
|
||||
frameBorder="0"
|
||||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${`${url + ticket2}/${view2}${param}`}`}
|
||||
src={`${`${url + ticket4}/${view2}${param}`}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
height="650"
|
||||
frameBorder="0"
|
||||
/>
|
||||
)}
|
||||
|
|
@ -367,7 +353,7 @@ export default function ExecutiveDashboard() {
|
|||
</Card>
|
||||
</div>
|
||||
<div className="w-full mt-3">
|
||||
<Card className="rounded-sm p-3 h-[850px]">
|
||||
<Card className="rounded-sm p-3 h-[750px]">
|
||||
<div className="flex flex-row justify-between">
|
||||
<p className="text-base font-semibold">
|
||||
Heatmap Konten Dengan Interaksi
|
||||
|
|
@ -378,18 +364,18 @@ export default function ExecutiveDashboard() {
|
|||
<LucideBoxSelect />
|
||||
</div>
|
||||
<div className="my-5">
|
||||
{ticket3 == "" ? (
|
||||
{ticket5 == "" ? (
|
||||
<iframe
|
||||
src={`${baseUrl + view3 + param}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
height="600"
|
||||
frameBorder="0"
|
||||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${`${url + ticket3}/${view3}${param}`}`}
|
||||
src={`${`${url + ticket5}/${view3}${param}`}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
height="600"
|
||||
frameBorder="0"
|
||||
/>
|
||||
)}
|
||||
|
|
@ -397,7 +383,7 @@ export default function ExecutiveDashboard() {
|
|||
</Card>
|
||||
</div>
|
||||
<div className="w-full mt-3">
|
||||
<Card className="rounded-sm p-3 h-[300px]">
|
||||
<Card className="rounded-sm p-3 h-auto">
|
||||
<div className="flex flex-row justify-between">
|
||||
<p className="text-base font-semibold">Emergency Issue</p>
|
||||
<LucideBoxSelect />
|
||||
|
|
@ -405,7 +391,7 @@ export default function ExecutiveDashboard() {
|
|||
|
||||
<div className="flex flex-col">
|
||||
<div className="my-5">
|
||||
{ticket1 == "" ? (
|
||||
{ticket6 == "" ? (
|
||||
<iframe
|
||||
src={`${baseUrl + view1 + param}`}
|
||||
width="100%"
|
||||
|
|
@ -414,7 +400,7 @@ export default function ExecutiveDashboard() {
|
|||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${`${url + ticket1}/${view1}${param}`}`}
|
||||
src={`${`${url + ticket6}/${view1}${param}`}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
frameBorder="0"
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import {
|
|||
getTicketingEscalationPagination,
|
||||
listTicketingInternal,
|
||||
} from "@/service/communication/communication";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const CollaborationTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -88,7 +89,7 @@ const CollaborationTable = () => {
|
|||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -13,30 +13,36 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { format } from "date-fns";
|
||||
import { Link, useRouter } from "@/i18n/routing";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => <span> {row.getValue("no")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Pertanyaan",
|
||||
header: t("question"),
|
||||
cell: ({ row }) => (
|
||||
<span className="normal-case"> {row.getValue("title")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "commentFromUserName",
|
||||
header: "CreateBy",
|
||||
header: t("sender"),
|
||||
cell: ({ row }) => (
|
||||
<span className="normal-case">{row.getValue("commentFromUserName")}</span>
|
||||
<span className="normal-case">
|
||||
{row.getValue("commentFromUserName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "Type",
|
||||
header: "Channel",
|
||||
header: t("type"),
|
||||
cell: ({ row }) => {
|
||||
const type = row.original.type;
|
||||
return <span className="normal-case">{type?.name || "N/A"}</span>;
|
||||
|
|
@ -44,7 +50,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Waktu",
|
||||
header: t("time"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -69,7 +75,9 @@ const columns: ColumnDef<any>[] = [
|
|||
: "bg-red-100 text-red-600"; // Gaya untuk "Closed"
|
||||
|
||||
return (
|
||||
<Badge className={`rounded-full px-5 ${statusStyles}`}>{status}</Badge>
|
||||
<Badge className={`rounded-full px-5 ${statusStyles}`}>
|
||||
{status}
|
||||
</Badge>
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
@ -77,7 +85,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const router = useRouter();
|
||||
|
|
@ -109,6 +117,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -13,30 +13,36 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { format } from "date-fns";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => <span> {row.getValue("no")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Pertanyaan",
|
||||
header: t("question"),
|
||||
cell: ({ row }) => (
|
||||
<span className="normal-case"> {row.getValue("title")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "commentFromUserName",
|
||||
header: "Penerima",
|
||||
header: t("sender"),
|
||||
cell: ({ row }) => (
|
||||
<span className="normal-case">{row.getValue("commentFromUserName")}</span>
|
||||
<span className="normal-case">
|
||||
{row.getValue("commentFromUserName")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "type",
|
||||
header: "Penerima",
|
||||
header: t("type"),
|
||||
cell: ({ row }) => {
|
||||
const type = row.original.type; // Akses properti category
|
||||
return <span className="normal-case">{type?.name || "N/A"}</span>;
|
||||
|
|
@ -44,7 +50,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Waktu",
|
||||
header: t("time"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -69,7 +75,9 @@ const columns: ColumnDef<any>[] = [
|
|||
: "bg-red-100 text-red-600"; // Gaya untuk "Closed"
|
||||
|
||||
return (
|
||||
<Badge className={`rounded-full px-5 ${statusStyles}`}>{status}</Badge>
|
||||
<Badge className={`rounded-full px-5 ${statusStyles}`}>
|
||||
{status}
|
||||
</Badge>
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
@ -77,7 +85,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -105,6 +113,8 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default columns;
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import {
|
|||
getTicketingEscalationPagination,
|
||||
listTicketingInternal,
|
||||
} from "@/service/communication/communication";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const EscalationTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -87,7 +88,7 @@ const EscalationTable = () => {
|
|||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -13,23 +13,27 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
import { format } from "date-fns";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => <span> {row.getValue("no")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Pertanyaan",
|
||||
header: t("question"),
|
||||
cell: ({ row }) => (
|
||||
<span className="normal-case"> {row.getValue("title")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdBy",
|
||||
header: "Pengirim",
|
||||
header: t("sender"),
|
||||
cell: ({ row }) => {
|
||||
const createdBy = row.original.createdBy; // Akses properti category
|
||||
return (
|
||||
|
|
@ -39,7 +43,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "sendTo",
|
||||
header: "Penerima",
|
||||
header: t("sendto"),
|
||||
cell: ({ row }) => {
|
||||
const sendTo = row.original.sendTo; // Akses properti category
|
||||
return <span className="normal-case">{sendTo?.fullname || "N/A"}</span>;
|
||||
|
|
@ -47,7 +51,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Waktu",
|
||||
header: t("time"),
|
||||
cell: ({ row }) => {
|
||||
const createdAt = row.getValue("createdAt") as
|
||||
| string
|
||||
|
|
@ -64,7 +68,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
|
|
@ -104,6 +108,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ import {
|
|||
} from "@/service/content/content";
|
||||
import { listTicketingInternal } from "@/service/communication/communication";
|
||||
import { Link } from "@/components/navigation";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const InternalTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -88,7 +89,7 @@ const InternalTable = () => {
|
|||
const userLevelId = getCookiesDecrypt("ulie");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -18,11 +18,15 @@ import Swal from "sweetalert2";
|
|||
import { error } from "@/lib/swal";
|
||||
import { deleteMedia } from "@/service/content/content";
|
||||
import { publishContest } from "@/service/contest/contest";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
header: t("no"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -35,7 +39,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "hastagCode",
|
||||
header: "Kode",
|
||||
header: t("code"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -51,7 +55,7 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "theme",
|
||||
header: "Judul",
|
||||
header: t("title"),
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
|
|
@ -64,21 +68,23 @@ const columns: ColumnDef<any>[] = [
|
|||
},
|
||||
{
|
||||
accessorKey: "duration",
|
||||
header: "Durasi ",
|
||||
header: t("duration"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("duration")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "targetOutput",
|
||||
header: "Target Output ",
|
||||
header: t("target-output"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("targetOutput")}</span>
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("targetOutput")}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "targetParticipantTopLevel",
|
||||
header: "Target Participant ",
|
||||
header: t("target-participant"),
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">
|
||||
{row.getValue("targetParticipantTopLevel")}
|
||||
|
|
@ -98,26 +104,28 @@ const columns: ColumnDef<any>[] = [
|
|||
const userRoleId: number = Number(getCookiesDecrypt("urie"));
|
||||
const userLevelNumber: number = Number(getCookiesDecrypt("ulne"));
|
||||
|
||||
// Mengambil data dari row.original agar lebih aman
|
||||
const isPublishForAll: boolean = Boolean(row.original.isPublishForAll);
|
||||
const isPublishForMabes: boolean = Boolean(
|
||||
row.original.isPublishForMabes
|
||||
);
|
||||
|
||||
// Logika status berdasarkan role dan data dari API
|
||||
const isPending: boolean =
|
||||
(userRoleId === 3 && userLevelNumber === 1 && !isPublishForAll) || // Role 3 dengan level 1 hanya publish jika isPublishForAll true
|
||||
((userRoleId === 11 || userRoleId === 12) && !isPublishForMabes); // Role 11 dan 12 hanya publish jika isPublishForMabes true
|
||||
(userRoleId === 3 && userLevelNumber === 1 && !isPublishForAll) ||
|
||||
((userRoleId === 11 || userRoleId === 12) && !isPublishForMabes);
|
||||
|
||||
const isTerkirim: boolean = isPublishForMabes && !isPublishForAll;
|
||||
|
||||
return (
|
||||
<Badge
|
||||
className={`whitespace-nowrap px-2 py-1 rounded-full ${
|
||||
isPending
|
||||
? "bg-orange-100 text-orange-600" // Warna kuning untuk "Pending"
|
||||
: isTerkirim
|
||||
? "bg-blue-100 text-blue-600" // Warna biru untuk "Terkirim"
|
||||
: "bg-green-100 text-green-600" // Warna hijau untuk "Publish"
|
||||
}`}
|
||||
>
|
||||
{isPending ? "Pending" : "Publish"}
|
||||
{isPending ? "Pending" : isTerkirim ? "Terkirim" : "Publish"}
|
||||
</Badge>
|
||||
);
|
||||
},
|
||||
|
|
@ -126,7 +134,7 @@ const columns: ColumnDef<any>[] = [
|
|||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
header: t("action"),
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
|
@ -222,6 +230,9 @@ const columns: ColumnDef<any>[] = [
|
|||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
];
|
||||
|
||||
export default columns;
|
||||
return columns;
|
||||
};
|
||||
|
||||
export default useTableColumns;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import { useRouter, useSearchParams } from "next/navigation";
|
|||
import TablePagination from "@/components/table/table-pagination";
|
||||
import columns from "./columns";
|
||||
import { listContest } from "@/service/contest/contest";
|
||||
import useTableColumns from "./columns";
|
||||
|
||||
const TaskTable = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -63,7 +64,7 @@ const TaskTable = () => {
|
|||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState<string>("");
|
||||
|
||||
const columns = useTableColumns();
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
columns,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"use client";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
|
|
@ -30,14 +31,6 @@ const AudioSliderPage = () => {
|
|||
initFetch();
|
||||
}, [page, limit, search]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (audioData?.length > 0) {
|
||||
// shuffleAndSetVideos();
|
||||
// const interval = setInterval(shuffleAndSetVideos, 5000);
|
||||
// return () => clearInterval(interval); // Cleanup interval on unmount
|
||||
// }
|
||||
// }, [audioData]);
|
||||
|
||||
const initFetch = async () => {
|
||||
const response = await listCuratedContent(search, limit, page - 1, 4, "1");
|
||||
console.log(response);
|
||||
|
|
@ -48,11 +41,6 @@ const AudioSliderPage = () => {
|
|||
setDisplayAudio(contentData);
|
||||
};
|
||||
|
||||
// const shuffleAndSetVideos = () => {
|
||||
// const shuffled = shuffleArray([...audioData]);
|
||||
// setDisplayAudio(shuffled.slice(0, 3));
|
||||
// };
|
||||
|
||||
const shuffleArray = (array: any[]) => {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
|
|
@ -62,18 +50,29 @@ const AudioSliderPage = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Carousel className="w-full pr-3">
|
||||
<CarouselContent>
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<CarouselItem key={index}>
|
||||
<div className="p-1 flex flex-row md:basis-1/2 lg:basis-1/2 gap-3">
|
||||
{displayAudio?.map((audio: any) => (
|
||||
<div className="w-full px-2">
|
||||
{displayAudio.length > 0 && (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<h2 className="text-xl font-semibold">Audio</h2>
|
||||
<Link
|
||||
href={`/shared/curated-content//giat-routine/audio/detail/${audio.id}`}
|
||||
key={audio?.id}
|
||||
className="flex flex-col sm:flex-row items-center hover:scale-100 transition-transform duration-300 bg-white dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full"
|
||||
href={"/shared/curated-content/giat-routine/video/all"}
|
||||
className="text-sm text-gray-500 hover:text-gray-700 flex items-center"
|
||||
>
|
||||
<div className="flex items-center justify-center bg-red-500 text-white rounded-lg w-12 h-12">
|
||||
Lihat Semua <Icon icon="lucide:arrow-right" className="ml-1" />
|
||||
</Link>
|
||||
</div>
|
||||
<Carousel className="w-full">
|
||||
<CarouselContent>
|
||||
{displayAudio.map((audio, index) => (
|
||||
<CarouselItem key={index} className="md:basis-1/3 lg:basis-1/3">
|
||||
<div className="p-2">
|
||||
<Card className=" shadow-md rounded-lg overflow-hidden">
|
||||
<Link
|
||||
href={`/shared/curated-content/giat-routine/audio/detail/${audio.id}`}
|
||||
>
|
||||
<div className="flex flex-row items-center gap-3">
|
||||
<div className="flex items-center justify-center bg-red-500 text-white rounded-lg w-12 h-12 mx-3 my-3">
|
||||
<svg
|
||||
width="28"
|
||||
height="28"
|
||||
|
|
@ -93,8 +92,9 @@ const AudioSliderPage = () => {
|
|||
{audio?.title}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</Card>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
|
|
@ -102,6 +102,9 @@ const AudioSliderPage = () => {
|
|||
<CarouselPrevious />
|
||||
<CarouselNext />
|
||||
</Carousel>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -574,35 +574,36 @@ export default function DetailAudio() {
|
|||
key={data.id}
|
||||
className="flex items-center gap-3 mt-2"
|
||||
>
|
||||
{/* <img
|
||||
className="object-cover w-20 h-20"
|
||||
src={data.thumbnailUrl} // Assuming `thumbnailUrl` is the property that contains the URL for the thumbnail image
|
||||
alt={`Thumbnail ${index}`}
|
||||
/> */}
|
||||
<Music className="object-cover w-32 h-32" />
|
||||
<div className="flex flex-wrap lg:flex-row gap-3 items-center">
|
||||
{/* Mabes Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "mabes"} // Automatically checks if placement matches
|
||||
disabled // To reflect read-only behavior
|
||||
checked={data.placements === "mabes"}
|
||||
disabled
|
||||
/>
|
||||
<span>Nasional</span>
|
||||
</label>
|
||||
|
||||
{/* Polda Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "polda"} // Automatically checks if placement matches
|
||||
checked={data.placements === "polda"}
|
||||
disabled
|
||||
/>
|
||||
<span>Wilayah</span>
|
||||
</label>
|
||||
|
||||
{/* International Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"} // Automatically checks if placement matches
|
||||
checked={data.placements === "satker"}
|
||||
disabled
|
||||
/>
|
||||
<span>Satker</span>
|
||||
</label>
|
||||
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"}
|
||||
disabled
|
||||
/>
|
||||
<span>International</span>
|
||||
|
|
|
|||
|
|
@ -580,28 +580,33 @@ export default function DetailDocument() {
|
|||
alt={data.fileName}
|
||||
/>
|
||||
<div className="flex flex-wrap lg:flex-row gap-3 items-center">
|
||||
{/* Mabes Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "mabes"} // Automatically checks if placement matches
|
||||
disabled // To reflect read-only behavior
|
||||
checked={data.placements === "mabes"}
|
||||
disabled
|
||||
/>
|
||||
<span>Nasional</span>
|
||||
</label>
|
||||
|
||||
{/* Polda Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "polda"} // Automatically checks if placement matches
|
||||
checked={data.placements === "polda"}
|
||||
disabled
|
||||
/>
|
||||
<span>Wilayah</span>
|
||||
</label>
|
||||
|
||||
{/* International Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"} // Automatically checks if placement matches
|
||||
checked={data.placements === "satker"}
|
||||
disabled
|
||||
/>
|
||||
<span>Satker</span>
|
||||
</label>
|
||||
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"}
|
||||
disabled
|
||||
/>
|
||||
<span>International</span>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
"use client";
|
||||
import { Link } from "@/components/navigation";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
|
|
@ -30,14 +31,6 @@ const TeksSliderPage = () => {
|
|||
initFetch();
|
||||
}, [page, limit, search]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (documentData?.length > 0) {
|
||||
// shuffleAndSetVideos();
|
||||
// const interval = setInterval(shuffleAndSetVideos, 5000);
|
||||
// return () => clearInterval(interval); // Cleanup interval on unmount
|
||||
// }
|
||||
// }, [documentData]);
|
||||
|
||||
const initFetch = async () => {
|
||||
const response = await listCuratedContent(search, limit, page - 1, 3, "1");
|
||||
console.log(response);
|
||||
|
|
@ -47,25 +40,26 @@ const TeksSliderPage = () => {
|
|||
setHasData(displayDocument && displayDocument.length > 0);
|
||||
setDisplayDocument(contentData);
|
||||
};
|
||||
// const shuffleAndSetVideos = () => {
|
||||
// const shuffled = shuffleArray([...documentData]);
|
||||
// setDisplayDocument(shuffled.slice(0, 2));
|
||||
// };
|
||||
|
||||
// const shuffleArray = (array: any[]) => {
|
||||
// for (let i = array.length - 1; i > 0; i--) {
|
||||
// const j = Math.floor(Math.random() * (i + 1));
|
||||
// [array[i], array[j]] = [array[j], array[i]];
|
||||
// }
|
||||
// return array;
|
||||
// };
|
||||
|
||||
return (
|
||||
<Carousel className="w-full pr-3">
|
||||
<div className="w-full px-2">
|
||||
{displayDocument.length > 0 && (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<h2 className="text-xl font-semibold">Teks</h2>
|
||||
<Link
|
||||
href={"/shared/curated-content/giat-routine/video/all"}
|
||||
className="text-sm text-gray-500 hover:text-gray-700 flex items-center"
|
||||
>
|
||||
Lihat Semua <Icon icon="lucide:arrow-right" className="ml-1" />
|
||||
</Link>
|
||||
</div>
|
||||
<Carousel className="w-full">
|
||||
<CarouselContent>
|
||||
<CarouselItem>
|
||||
<div className="p-1 flex flex-row md:basis-1/2 lg:basis-1/3 gap-3">
|
||||
{displayDocument?.map((document: any) => (
|
||||
{displayDocument.map((document, index) => (
|
||||
<CarouselItem key={index} className="md:basis-1/3 lg:basis-1/3">
|
||||
<div className="p-2">
|
||||
<Card className=" shadow-md rounded-lg overflow-hidden">
|
||||
<Link
|
||||
href={`/shared/curated-content/giat-routine/document/detail/${document.id}`}
|
||||
key={document?.id}
|
||||
|
|
@ -88,9 +82,12 @@ const TeksSliderPage = () => {
|
|||
|
||||
<div className="flex flex-col flex-1">
|
||||
<div className="text-gray-500 dark:text-gray-400 flex flex-row text-sm">
|
||||
{formatDateToIndonesian(new Date(document?.createdAt))}{" "}
|
||||
{formatDateToIndonesian(
|
||||
new Date(document?.createdAt)
|
||||
)}{" "}
|
||||
{document?.timezone ? document?.timezone : "WIB"} |{" "}
|
||||
<Icon icon="formkit:eye" width="15" height="15" /> 518
|
||||
<Icon icon="formkit:eye" width="15" height="15" />{" "}
|
||||
518
|
||||
</div>
|
||||
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm">
|
||||
{document?.title}
|
||||
|
|
@ -111,13 +108,17 @@ const TeksSliderPage = () => {
|
|||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</Card>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
<CarouselPrevious />
|
||||
<CarouselNext />
|
||||
</Carousel>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -52,9 +52,7 @@ const ImageAllPage = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="ml-5 pb-3">
|
||||
<div className="flex justify-between items-center mx-3">
|
||||
<Label className="text-base">Image</Label>
|
||||
</div>
|
||||
<div className="flex justify-between items-center mx-3"></div>
|
||||
<div className="px-5 my-5">
|
||||
<ImageSliderPage />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import { getCookiesDecrypt } from "@/lib/utils";
|
|||
import { close, loading } from "@/lib/swal";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { htmlToString } from "@/utils/globals";
|
||||
import { Link } from "@/i18n/routing";
|
||||
|
||||
const detailSchema = z.object({
|
||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||
|
|
@ -443,8 +444,13 @@ export default function DetailImage() {
|
|||
<p className="text-blue-500">Kotak Saran (0)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href={
|
||||
"/shared/curated-content/giat-routine/image/detail/content-rewrite"
|
||||
}
|
||||
>
|
||||
<Button>Content Rewrite</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -534,25 +540,31 @@ export default function DetailImage() {
|
|||
{/* Mabes Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "mabes"} // Automatically checks if placement matches
|
||||
disabled // To reflect read-only behavior
|
||||
checked={data.placements === "mabes"}
|
||||
disabled
|
||||
/>
|
||||
<span>Nasional</span>
|
||||
</label>
|
||||
|
||||
{/* Polda Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "polda"} // Automatically checks if placement matches
|
||||
checked={data.placements === "polda"}
|
||||
disabled
|
||||
/>
|
||||
<span>Wilayah</span>
|
||||
</label>
|
||||
|
||||
{/* International Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"} // Automatically checks if placement matches
|
||||
checked={data.placements === "satker"}
|
||||
disabled
|
||||
/>
|
||||
<span>Satker</span>
|
||||
</label>
|
||||
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"}
|
||||
disabled
|
||||
/>
|
||||
<span>International</span>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,349 @@
|
|||
"use client";
|
||||
import { useState } from "react";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import CustomEditor from "@/components/editor/custom-editor";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Link } from "@/i18n/routing";
|
||||
|
||||
const imageSchema = z.object({
|
||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||
description: z
|
||||
.string()
|
||||
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }),
|
||||
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
||||
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
||||
});
|
||||
|
||||
const ContentRewritePage = () => {
|
||||
const [step, setStep] = useState("configuration");
|
||||
const [selectedLanguage, setSelectedLanguage] = useState("");
|
||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||
const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
||||
const [selectedSize, setSelectedSize] = useState("");
|
||||
const [selectedSort, setSelectedSort] = useState("");
|
||||
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
||||
null
|
||||
);
|
||||
|
||||
type ImageSchema = z.infer<typeof imageSchema>;
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm<ImageSchema>({
|
||||
resolver: zodResolver(imageSchema),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
<h2 className="text-xl font-semibold mb-4">Content Rewrite</h2>
|
||||
<div className="flex items-center space-x-6 mb-6">
|
||||
<div className="flex flex-col items-center">
|
||||
<div
|
||||
className={`w-8 h-8 flex items-center justify-center border-2 rounded-full ${
|
||||
step === "configuration"
|
||||
? "border-blue-500 text-blue-500"
|
||||
: "border-gray-400 text-gray-400"
|
||||
}`}
|
||||
>
|
||||
●
|
||||
</div>
|
||||
<p
|
||||
className={
|
||||
step === "configuration"
|
||||
? "text-blue-500 font-semibold"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
Configuration
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className={`flex-1 h-0.5 ${
|
||||
step === "draft"
|
||||
? "bg-blue-500 text-blue-500"
|
||||
: "bg-gray-400 text-gray-400"
|
||||
}`}
|
||||
></div>
|
||||
<div className="flex flex-col items-center">
|
||||
<div
|
||||
className={`w-8 h-8 flex items-center justify-center border-2 rounded-full ${
|
||||
step === "draft"
|
||||
? "border-blue-500 text-blue-500"
|
||||
: "border-gray-400 text-gray-400"
|
||||
}`}
|
||||
>
|
||||
○
|
||||
</div>
|
||||
<p
|
||||
className={
|
||||
step === "draft"
|
||||
? "text-blue-500 font-semibold"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
Draft
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className={`flex-1 h-0.5 ${
|
||||
step === "publish"
|
||||
? "bg-blue-500 text-blue-500"
|
||||
: "bg-gray-400 text-gray-400"
|
||||
}`}
|
||||
></div>
|
||||
<div className="flex flex-col items-center">
|
||||
<div
|
||||
className={`w-8 h-8 flex items-center justify-center border-2 rounded-full ${
|
||||
step === "publish"
|
||||
? "border-blue-500 text-blue-500"
|
||||
: "border-gray-400 text-gray-400"
|
||||
}`}
|
||||
>
|
||||
○
|
||||
</div>
|
||||
<p
|
||||
className={
|
||||
step === "publish"
|
||||
? "text-blue-500 font-semibold"
|
||||
: "text-gray-400"
|
||||
}
|
||||
>
|
||||
Publish
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{step === "configuration" && (
|
||||
<>
|
||||
<div className="flex flex-row gap-3">
|
||||
<div className="space-y-2 py-3 w-4/12">
|
||||
<Label>Bahasa</Label>
|
||||
<Select onValueChange={setSelectedLanguage}>
|
||||
<SelectTrigger size="md">
|
||||
<SelectValue placeholder="Pilih" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="id">Indonesia</SelectItem>
|
||||
<SelectItem value="en">English</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2 py-3 w-4/12">
|
||||
<Label>Writing Style</Label>
|
||||
<Select onValueChange={setSelectedWritingStyle}>
|
||||
<SelectTrigger size="md">
|
||||
<SelectValue placeholder="Pilih" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="friendly">Friendly</SelectItem>
|
||||
<SelectItem value="profesional">Profesional</SelectItem>
|
||||
<SelectItem value="informational">
|
||||
Informational
|
||||
</SelectItem>
|
||||
<SelectItem value="neutral">Neutral</SelectItem>
|
||||
<SelectItem value="witty">Witty</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-2 py-3 w-4/12">
|
||||
<Label>Article Size</Label>
|
||||
<Select onValueChange={setSelectedSize}>
|
||||
<SelectTrigger size="md">
|
||||
<SelectValue placeholder="Pilih" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="news">
|
||||
News (300 - 900 words)
|
||||
</SelectItem>
|
||||
<SelectItem value="info">
|
||||
Info (900 - 2000 words)
|
||||
</SelectItem>
|
||||
<SelectItem value="detail">
|
||||
Detail (2000 - 5000 words)
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<Label>Configuration</Label>
|
||||
<Input
|
||||
placeholder="Type your custom instruction here!"
|
||||
className="h-20"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setStep("draft")}
|
||||
className=" bg-blue-600 text-white"
|
||||
>
|
||||
Selanjutnya
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{step === "draft" && (
|
||||
<div>
|
||||
<div className="flex flex-row justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="accepted"
|
||||
// checked={filtered.includes("polri")}
|
||||
// onCheckedChange={(e) => handleFilter("polri", Boolean(e))}
|
||||
/>
|
||||
<label
|
||||
htmlFor="accepted"
|
||||
className="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
Select All
|
||||
</label>
|
||||
</div>
|
||||
<div className="space-y-2 py-3">
|
||||
<div className="flex flex-row items-center">
|
||||
<Label className="w-[50px]">Sort by</Label>
|
||||
<Select onValueChange={setSelectedSort}>
|
||||
<SelectTrigger size="sm" className="w-[150px]">
|
||||
<SelectValue placeholder="Pilih" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="id">Indonesia</SelectItem>
|
||||
<SelectItem value="en">English</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{[
|
||||
{
|
||||
src: "/assets/img/image1.png",
|
||||
alt: "Article 1",
|
||||
title: "Kurang dari 24 Jam Polres Muara Enim Ungka...",
|
||||
},
|
||||
{
|
||||
src: "/assets/img/image3.png",
|
||||
alt: "Article 2",
|
||||
title: "Kurang dari 24 Jam Polres Muara Enim Ungka...",
|
||||
},
|
||||
{
|
||||
src: "/assets/img/image3.png",
|
||||
alt: "Article 3",
|
||||
title: "Polres Magelang Kota Konferensi Pers Terkait...",
|
||||
},
|
||||
].map((article, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="border rounded-md overflow-hidden relative"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="absolute top-2 left-2 w-5 h-5 cursor-pointer"
|
||||
/>
|
||||
|
||||
<img
|
||||
src={article.src}
|
||||
alt={article.alt}
|
||||
className="w-full h-40 object-cover"
|
||||
/>
|
||||
|
||||
<p className="p-2 text-sm">{article.title}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row justify-between mt-3">
|
||||
<Button
|
||||
onClick={() => setStep("configuration")}
|
||||
variant={"outline"}
|
||||
color="primary"
|
||||
>
|
||||
Kembali
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setStep("publish")}
|
||||
variant={"default"}
|
||||
color="primary"
|
||||
>
|
||||
Selanjutnya
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === "publish" && (
|
||||
<div>
|
||||
<div className="py-3">
|
||||
<div className="flex flex-row justify-between items-center mb-3">
|
||||
<Label>940 Words</Label>
|
||||
<Link
|
||||
href={`/contributor/content/image/update-seo/${selectedArticleId}`}
|
||||
>
|
||||
<Button
|
||||
className="mb-2"
|
||||
size="sm"
|
||||
variant={"outline"}
|
||||
color="primary"
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<Controller
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<CustomEditor
|
||||
onChange={onChange}
|
||||
// initialData={articleBody}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{/* {errors.description?.message && (
|
||||
<p className="text-red-400 text-sm">
|
||||
{errors.description.message}
|
||||
</p>
|
||||
)} */}
|
||||
</div>
|
||||
<div className="flex flex-row justify-between mt-3">
|
||||
<Button
|
||||
onClick={() => setStep("configuration")}
|
||||
variant={"outline"}
|
||||
color="primary"
|
||||
>
|
||||
Kembali
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setStep("publish")}
|
||||
variant={"default"}
|
||||
color="primary"
|
||||
>
|
||||
Selanjutnya
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContentRewritePage;
|
||||
|
|
@ -10,111 +10,85 @@ import {
|
|||
} from "@/components/ui/carousel";
|
||||
import { listCuratedContent } from "@/service/curated-content/curated-content";
|
||||
|
||||
import {
|
||||
formatDateToIndonesian,
|
||||
generateLocalizedPath,
|
||||
textEllipsis,
|
||||
} from "@/utils/globals";
|
||||
import { formatDateToIndonesian } from "@/utils/globals";
|
||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||
import {
|
||||
SortingState,
|
||||
ColumnFiltersState,
|
||||
VisibilityState,
|
||||
PaginationState,
|
||||
} from "@tanstack/react-table";
|
||||
import {
|
||||
useParams,
|
||||
usePathname,
|
||||
useRouter,
|
||||
useSearchParams,
|
||||
} from "next/navigation";
|
||||
import React, { Component, useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
type ImageData = {
|
||||
id: string;
|
||||
title: string;
|
||||
createdAt: string;
|
||||
timezone: string;
|
||||
thumbnailLink: string;
|
||||
clickCount: string;
|
||||
};
|
||||
|
||||
const ImageSliderPage = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const [imageData, setImageData] = useState<any>();
|
||||
const [displayImage, setDisplayImage] = useState<any[]>([]);
|
||||
const [imageData, setImageData] = useState<ImageData[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState("");
|
||||
const [limit] = useState(10);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [page, limit, search]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (imageData?.length > 0) {
|
||||
// shuffleAndSetVideos();
|
||||
// const interval = setInterval(shuffleAndSetVideos, 5000);
|
||||
// return () => clearInterval(interval); // Cleanup interval on unmount
|
||||
// }
|
||||
// }, [imageData]);
|
||||
}, [page]);
|
||||
|
||||
const fetchData = async () => {
|
||||
const response = await listCuratedContent(search, limit, page - 1, 1, "1");
|
||||
console.log(response);
|
||||
|
||||
const data = response?.data?.data;
|
||||
const contentData = data?.content;
|
||||
setImageData(contentData);
|
||||
const response = await listCuratedContent("", limit, page - 1, 1, "1");
|
||||
const data = response?.data?.data?.content || [];
|
||||
setImageData(data);
|
||||
};
|
||||
|
||||
// const shuffleAndSetVideos = () => {
|
||||
// const shuffled = shuffleArray([...imageData]);
|
||||
// setDisplayImage(shuffled.slice(0, 3));
|
||||
// };
|
||||
|
||||
// const shuffleArray = (array: any[]) => {
|
||||
// for (let i = array.length - 1; i > 0; i--) {
|
||||
// const j = Math.floor(Math.random() * (i + 1));
|
||||
// [array[i], array[j]] = [array[j], array[i]];
|
||||
// }
|
||||
// return array;
|
||||
// };
|
||||
return (
|
||||
<Carousel className="w-full pr-3">
|
||||
<CarouselContent>
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<CarouselItem key={index}>
|
||||
<div className="p-1 flex flex-row md:basis-1/2 lg:basis-1/2 gap-3">
|
||||
{imageData?.map((image: any) => (
|
||||
<Card
|
||||
key={image?.id}
|
||||
className="hover:sc ale-110 transition-transform duration-300"
|
||||
>
|
||||
<div className="w-full px-2">
|
||||
{imageData.length > 0 && (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<h2 className="text-xl font-semibold">Foto</h2>
|
||||
<Link
|
||||
href={`/shared/curated-content//giat-routine/image/detail/${image.id}`}
|
||||
href={"/shared/curated-content/giat-routine/image/all"}
|
||||
className="text-sm text-gray-500 hover:text-gray-700 flex items-center"
|
||||
>
|
||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||
Lihat Semua <Icon icon="lucide:arrow-right" className="ml-1" />
|
||||
</Link>
|
||||
</div>
|
||||
<Carousel className="w-full">
|
||||
<CarouselContent>
|
||||
{imageData.map((image, index) => (
|
||||
<CarouselItem key={index} className="md:basis-1/3 lg:basis-1/3">
|
||||
<div className="p-2">
|
||||
<Card className="shadow-md rounded-lg overflow-hidden">
|
||||
<Link
|
||||
href={`/shared/curated-content/giat-routine/image/detail/${image.id}`}
|
||||
>
|
||||
<CardContent className="p-0">
|
||||
<img
|
||||
src={image?.thumbnailLink}
|
||||
className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg"
|
||||
alt={image?.title}
|
||||
className="w-full h-56 object-cover rounded-t-lg"
|
||||
/>
|
||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
|
||||
{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"
|
||||
d="M7.707 10.293a1 1 0 1 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l3-3a1 1 0 0 0-1.414-1.414L11 11.586V6h5a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h5v5.586zM9 4a1 1 0 0 1 2 0v2H9z"
|
||||
<div className="p-3">
|
||||
<p className="text-xs text-gray-500">
|
||||
{formatDateToIndonesian(
|
||||
new Date(image?.createdAt)
|
||||
)}{" "}
|
||||
{image?.timezone || "WIB"} |
|
||||
<Icon
|
||||
icon="formkit:eye"
|
||||
width="15"
|
||||
height="15"
|
||||
className="inline ml-1"
|
||||
/>
|
||||
</svg>{" "}
|
||||
</div>
|
||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||
{image?.clickCount}
|
||||
</p>
|
||||
<h3 className="font-semibold text-sm truncate">
|
||||
{image?.title}
|
||||
</h3>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Link>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
|
|
@ -122,11 +96,9 @@ const ImageSliderPage = () => {
|
|||
<CarouselPrevious />
|
||||
<CarouselNext />
|
||||
</Carousel>
|
||||
// <div className="mx-3 px-5">
|
||||
// <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
|
||||
// </div>
|
||||
// </div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
CarouselNext,
|
||||
CarouselPrevious,
|
||||
} from "@/components/ui/carousel";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { listCuratedContent } from "@/service/curated-content/curated-content";
|
||||
import { getListContent } from "@/service/landing/landing";
|
||||
import { formatDateToIndonesian } from "@/utils/globals";
|
||||
|
|
@ -15,9 +16,18 @@ import { Icon } from "@iconify/react/dist/iconify.js";
|
|||
import image from "next/image";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
type VideoData = {
|
||||
id: string;
|
||||
title: string;
|
||||
createdAt: string;
|
||||
timezone: string;
|
||||
thumbnailLink: string;
|
||||
clickCount: string;
|
||||
};
|
||||
|
||||
const VideoSliderPage = () => {
|
||||
const [allVideoData, setAllVideoData] = useState<any[]>([]);
|
||||
const [displayVideos, setDisplayVideos] = useState<any[]>([]);
|
||||
const [videoData, setVideoData] = useState<VideoData[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
|
@ -26,79 +36,64 @@ const VideoSliderPage = () => {
|
|||
fetchData();
|
||||
}, [page, limit, search]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (allVideoData?.length > 0) {
|
||||
// shuffleAndSetVideos();
|
||||
// const interval = setInterval(shuffleAndSetVideos, 5000);
|
||||
// return () => clearInterval(interval); // Cleanup interval on unmount
|
||||
// }
|
||||
// }, [allVideoData]);
|
||||
|
||||
const fetchData = async () => {
|
||||
const response = await listCuratedContent(search, limit, page - 1, 2, "1");
|
||||
console.log(response);
|
||||
|
||||
const data = response?.data?.data;
|
||||
const contentData = data?.content;
|
||||
setAllVideoData(contentData);
|
||||
setVideoData(contentData);
|
||||
};
|
||||
|
||||
// const shuffleAndSetVideos = () => {
|
||||
// const shuffled = shuffleArray([...allVideoData]);
|
||||
// setDisplayVideos(shuffled.slice(0, 3));
|
||||
// };
|
||||
|
||||
// const shuffleArray = (array: any[]) => {
|
||||
// for (let i = array.length - 1; i > 0; i--) {
|
||||
// const j = Math.floor(Math.random() * (i + 1));
|
||||
// [array[i], array[j]] = [array[j], array[i]];
|
||||
// }
|
||||
// return array;
|
||||
// };
|
||||
|
||||
return (
|
||||
<Carousel className="w-full pr-3">
|
||||
<CarouselContent>
|
||||
{Array.from({ length: 5 }).map((_, index) => (
|
||||
<CarouselItem key={index}>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{allVideoData.map((video: any) => (
|
||||
<Card
|
||||
key={video?.id}
|
||||
className="hover:scale-110 transition-transform duration-300"
|
||||
<div className="w-full px-2">
|
||||
{videoData.length > 0 && (
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<h2 className="text-xl font-semibold">Video</h2>
|
||||
<Link
|
||||
href={"/shared/curated-content/giat-routine/video/all"}
|
||||
className="text-sm text-gray-500 hover:text-gray-700 flex items-center"
|
||||
>
|
||||
Lihat Semua <Icon icon="lucide:arrow-right" className="ml-1" />
|
||||
</Link>
|
||||
</div>
|
||||
<Carousel className="w-full">
|
||||
<CarouselContent>
|
||||
{videoData.map((video, index) => (
|
||||
<CarouselItem key={index} className="md:basis-1/3 lg:basis-1/3">
|
||||
<div className="p-2">
|
||||
<Card className="shadow-md rounded-lg overflow-hidden">
|
||||
<Link
|
||||
href={`/shared/curated-content/giat-routine/video/detail/${video.id}`}
|
||||
>
|
||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||
<CardContent className="p-0">
|
||||
<img
|
||||
src={video?.thumbnailLink}
|
||||
className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg"
|
||||
alt={video?.title}
|
||||
className="w-full h-56 object-cover rounded-t-lg"
|
||||
/>
|
||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
|
||||
{formatDateToIndonesian(new Date(video?.createdAt))}{" "}
|
||||
<div className="p-3">
|
||||
<p className="text-xs text-gray-500">
|
||||
{formatDateToIndonesian(
|
||||
new Date(video?.createdAt)
|
||||
)}{" "}
|
||||
{video?.timezone || "WIB"} |
|
||||
<Icon icon="formkit:eye" width="15" height="15" />
|
||||
{video?.clickCount}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
fill="#f00"
|
||||
d="M7.707 10.293a1 1 0 1 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l3-3a1 1 0 0 0-1.414-1.414L11 11.586V6h5a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h5v5.586zM9 4a1 1 0 0 1 2 0v2H9z"
|
||||
<Icon
|
||||
icon="formkit:eye"
|
||||
width="15"
|
||||
height="15"
|
||||
className="inline ml-1"
|
||||
/>
|
||||
</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?.clickCount}
|
||||
</p>
|
||||
<h3 className="font-semibold text-sm truncate">
|
||||
{video?.title}
|
||||
</h3>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Link>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
|
|
@ -106,6 +101,9 @@ const VideoSliderPage = () => {
|
|||
<CarouselPrevious />
|
||||
<CarouselNext />
|
||||
</Carousel>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -523,39 +523,39 @@ export default function DetailImage() {
|
|||
key={data.id}
|
||||
className="flex items-center gap-3 mt-2"
|
||||
>
|
||||
{/* <img
|
||||
className="object-cover w-20 h-20"
|
||||
src={data.thumbnailUrl} // Assuming `thumbnailUrl` is the property that contains the URL for the thumbnail image
|
||||
alt={`Thumbnail ${index}`}
|
||||
/> */}
|
||||
<img
|
||||
className="object-cover w-20 h-20 lg:w-32 lg:h-32"
|
||||
src={"/assets/video-icon.webp"}
|
||||
alt={` ${data.id}`}
|
||||
/>
|
||||
<div className="flex flex-wrap lg:flex-row gap-3 items-center">
|
||||
{/* Mabes Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "mabes"} // Automatically checks if placement matches
|
||||
disabled // To reflect read-only behavior
|
||||
checked={data.placements === "mabes"}
|
||||
disabled
|
||||
/>
|
||||
<span>Nasional</span>
|
||||
</label>
|
||||
|
||||
{/* Polda Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "polda"} // Automatically checks if placement matches
|
||||
checked={data.placements === "polda"}
|
||||
disabled
|
||||
/>
|
||||
<span>Wilayah</span>
|
||||
</label>
|
||||
|
||||
{/* International Checkbox */}
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"} // Automatically checks if placement matches
|
||||
checked={data.placements === "satker"}
|
||||
disabled
|
||||
/>
|
||||
<span>Satker</span>
|
||||
</label>
|
||||
|
||||
<label className=" cursor-pointer flex items-center gap-2">
|
||||
<Checkbox
|
||||
checked={data.placements === "international"}
|
||||
disabled
|
||||
/>
|
||||
<span>International</span>
|
||||
|
|
|
|||
|
|
@ -24,15 +24,19 @@ import AudioSliderPage from "./giat-routine/audio/audio";
|
|||
import ImageSliderPage from "./giat-routine/image/image";
|
||||
import TeksSliderPage from "./giat-routine/document/teks";
|
||||
import ContestTable from "../contest/components/contest-table";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const CuratedContentPage = () => {
|
||||
const t = useTranslations("Curation");
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="my-3">
|
||||
<Tabs defaultValue="giat-routine" className="w-full">
|
||||
<Card className="py-3 px-2 my-4">
|
||||
<p className="text-lg font-semibold ml-2">Kurasi Konten</p>
|
||||
<p className="text-lg font-semibold ml-2">
|
||||
{t("content-curation")}
|
||||
</p>
|
||||
<TabsList className="flex-wrap">
|
||||
<TabsTrigger
|
||||
value="giat-routine"
|
||||
|
|
@ -73,80 +77,15 @@ const CuratedContentPage = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="ml-5 pb-3">
|
||||
<div className="flex justify-between items-center mx-3">
|
||||
<Label className="text-base">Audio Visual</Label>
|
||||
|
||||
<div className="flex items-center">
|
||||
<Label>
|
||||
{" "}
|
||||
<Link
|
||||
href={
|
||||
"/shared/curated-content/giat-routine/video/all"
|
||||
}
|
||||
>
|
||||
Lihat Semua
|
||||
</Link>
|
||||
</Label>
|
||||
<ArrowRight size={18} className="text-slate-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-5 my-5">
|
||||
<VideoSliderPage />
|
||||
</div>
|
||||
<div className="flex justify-between items-center mx-3">
|
||||
<Label className="text-base">Audio</Label>
|
||||
<div className="flex items-center">
|
||||
<Label>
|
||||
{" "}
|
||||
<Link
|
||||
href={
|
||||
"/shared/curated-content/giat-routine/audio/all"
|
||||
}
|
||||
>
|
||||
Lihat Semua
|
||||
</Link>
|
||||
</Label>
|
||||
<ArrowRight size={18} className="text-slate-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-5 my-5">
|
||||
<AudioSliderPage />
|
||||
</div>
|
||||
<div className="flex justify-between items-center mx-3">
|
||||
<Label className="text-base">Foto</Label>
|
||||
<div className="flex items-center">
|
||||
<Label>
|
||||
{" "}
|
||||
<Link
|
||||
href={
|
||||
"/shared/curated-content/giat-routine/image/all"
|
||||
}
|
||||
>
|
||||
Lihat Semua
|
||||
</Link>
|
||||
</Label>
|
||||
<ArrowRight size={18} className="text-slate-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-5 my-5">
|
||||
<ImageSliderPage />
|
||||
</div>
|
||||
<div className="flex justify-between items-center mx-3">
|
||||
<Label className="text-base">Teks</Label>
|
||||
<div className="flex items-center">
|
||||
<Label>
|
||||
{" "}
|
||||
<Link
|
||||
href={
|
||||
"/shared/curated-content/giat-routine/document/all"
|
||||
}
|
||||
>
|
||||
Lihat Semua
|
||||
</Link>
|
||||
</Label>
|
||||
<ArrowRight size={18} className="text-slate-600" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-5 my-5">
|
||||
<TeksSliderPage />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -442,7 +442,22 @@ export default function FormAudio() {
|
|||
return;
|
||||
}
|
||||
|
||||
const requestData = {
|
||||
let requestData: {
|
||||
title: string;
|
||||
description: string;
|
||||
htmlDescription: string;
|
||||
fileTypeId: string;
|
||||
categoryId: any;
|
||||
subCategoryId: any;
|
||||
uploadedBy: string;
|
||||
statusId: string;
|
||||
publishedFor: string;
|
||||
creatorName: string;
|
||||
tags: string;
|
||||
isYoutube: boolean;
|
||||
isInternationalMedia: boolean;
|
||||
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||
} = {
|
||||
...data,
|
||||
title: finalTitle,
|
||||
description: finalDescription,
|
||||
|
|
@ -461,6 +476,10 @@ export default function FormAudio() {
|
|||
|
||||
let id = Cookies.get("idCreate");
|
||||
|
||||
if (scheduleId !== undefined) {
|
||||
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||
}
|
||||
|
||||
if (id == undefined) {
|
||||
const response = await createMedia(requestData);
|
||||
console.log("Form Data Submitted:", requestData);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ import { options } from "@fullcalendar/core/preact.js";
|
|||
import dynamic from "next/dynamic";
|
||||
import { getCsrfToken } from "@/service/auth";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { request } from "http";
|
||||
|
||||
interface FileWithPreview extends File {
|
||||
preview: string;
|
||||
|
|
@ -443,11 +444,28 @@ export default function FormImage() {
|
|||
const finalTags = tags.join(", ");
|
||||
const finalTitle = isSwitchOn ? title : data.title;
|
||||
const finalDescription = articleBody || data.description;
|
||||
|
||||
if (!finalDescription.trim()) {
|
||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||
return;
|
||||
}
|
||||
const requestData = {
|
||||
|
||||
let requestData: {
|
||||
title: string;
|
||||
description: string;
|
||||
htmlDescription: string;
|
||||
fileTypeId: string;
|
||||
categoryId: any;
|
||||
subCategoryId: any;
|
||||
uploadedBy: string;
|
||||
statusId: string;
|
||||
publishedFor: string;
|
||||
creatorName: string;
|
||||
tags: string;
|
||||
isYoutube: boolean;
|
||||
isInternationalMedia: boolean;
|
||||
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||
} = {
|
||||
...data,
|
||||
title: finalTitle,
|
||||
description: finalDescription,
|
||||
|
|
@ -466,14 +484,14 @@ export default function FormImage() {
|
|||
|
||||
let id = Cookies.get("idCreate");
|
||||
|
||||
if (scheduleId !== undefined) {
|
||||
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||
}
|
||||
|
||||
if (id == undefined) {
|
||||
const response = await createMedia(requestData);
|
||||
console.log("Form Data Submitted:", requestData);
|
||||
|
||||
// if (response?.error) {
|
||||
// MySwal.fire("Error", response?.message, "error");
|
||||
// return;
|
||||
// }
|
||||
Cookies.set("idCreate", response?.data?.data, { expires: 1 });
|
||||
id = response?.data?.data;
|
||||
|
||||
|
|
@ -489,16 +507,15 @@ export default function FormImage() {
|
|||
}
|
||||
|
||||
// Upload File
|
||||
const progressInfoArr = [];
|
||||
for (const item of files) {
|
||||
progressInfoArr.push({ percentage: 0, fileName: item.name });
|
||||
}
|
||||
const progressInfoArr = files.map((item) => ({
|
||||
percentage: 0,
|
||||
fileName: item.name,
|
||||
}));
|
||||
progressInfo = progressInfoArr;
|
||||
setIsStartUpload(true);
|
||||
setProgressList(progressInfoArr);
|
||||
|
||||
close();
|
||||
// showProgress();
|
||||
files.map(async (item: any, index: number) => {
|
||||
await uploadResumableFile(
|
||||
index,
|
||||
|
|
@ -509,8 +526,6 @@ export default function FormImage() {
|
|||
});
|
||||
|
||||
Cookies.remove("idCreate");
|
||||
|
||||
// MySwal.fire("Sukses", "Data berhasil disimpan.", "success");
|
||||
};
|
||||
|
||||
const onSubmit = (data: ImageSchema) => {
|
||||
|
|
|
|||
|
|
@ -394,6 +394,33 @@ export default function FormConvertSPIT() {
|
|||
return temp;
|
||||
};
|
||||
|
||||
// const setupPlacement = (
|
||||
// index: number,
|
||||
// category: string,
|
||||
// isChecked: boolean
|
||||
// ) => {
|
||||
// setFilePlacements((prev) =>
|
||||
// prev.map((placement, i) =>
|
||||
// i === index
|
||||
// ? isChecked
|
||||
// ? [...new Set([...placement, category])] // Tambahkan kategori jika belum ada
|
||||
// : placement.filter((item) => item !== category) // Hapus kategori jika ada
|
||||
// : placement
|
||||
// )
|
||||
// );
|
||||
// };
|
||||
|
||||
const handleSelectAll = (category: string, isChecked: boolean) => {
|
||||
setFilePlacements((prev: string[][]) =>
|
||||
prev.map(
|
||||
(placement: string[]) =>
|
||||
isChecked
|
||||
? Array.from(new Set([...placement, category])) // Konversi Set ke array dengan Array.from()
|
||||
: placement.filter((item: string) => item !== category) // Hapus jika ada
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const save = async (data: {
|
||||
contentTitle: string;
|
||||
contentDescription: string;
|
||||
|
|
@ -785,6 +812,66 @@ export default function FormConvertSPIT() {
|
|||
<div className="mt-3">
|
||||
<Label className="text-xl">Penempatan file</Label>
|
||||
</div>
|
||||
{files?.length > 1 && (
|
||||
<div className="flex flex-wrap gap-2 mt-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="all-content"
|
||||
onCheckedChange={(e) =>
|
||||
handleSelectAll("all", Boolean(e))
|
||||
}
|
||||
/>
|
||||
<label
|
||||
htmlFor="all-content"
|
||||
className="text-xs font-medium"
|
||||
>
|
||||
All
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="all-nasional"
|
||||
onCheckedChange={(e) =>
|
||||
handleSelectAll("mabes", Boolean(e))
|
||||
}
|
||||
/>
|
||||
<label
|
||||
htmlFor="all-nasional"
|
||||
className="text-xs font-medium"
|
||||
>
|
||||
All Nasional
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="all-wilayah"
|
||||
onCheckedChange={(e) =>
|
||||
handleSelectAll("polda", Boolean(e))
|
||||
}
|
||||
/>
|
||||
<label
|
||||
htmlFor="all-wilayah"
|
||||
className="text-xs font-medium"
|
||||
>
|
||||
All Wilayah
|
||||
</label>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="all-international"
|
||||
onCheckedChange={(e) =>
|
||||
handleSelectAll("international", Boolean(e))
|
||||
}
|
||||
/>
|
||||
<label
|
||||
htmlFor="all-international"
|
||||
className="text-xs font-medium"
|
||||
>
|
||||
All Internasional
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{files?.map((file, index) => (
|
||||
<div
|
||||
key={file.contentId}
|
||||
|
|
|
|||
|
|
@ -441,7 +441,22 @@ export default function FormTeks() {
|
|||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||
return;
|
||||
}
|
||||
const requestData = {
|
||||
let requestData: {
|
||||
title: string;
|
||||
description: string;
|
||||
htmlDescription: string;
|
||||
fileTypeId: string;
|
||||
categoryId: any;
|
||||
subCategoryId: any;
|
||||
uploadedBy: string;
|
||||
statusId: string;
|
||||
publishedFor: string;
|
||||
creatorName: string;
|
||||
tags: string;
|
||||
isYoutube: boolean;
|
||||
isInternationalMedia: boolean;
|
||||
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||
} = {
|
||||
...data,
|
||||
title: finalTitle,
|
||||
description: finalDescription,
|
||||
|
|
@ -460,6 +475,10 @@ export default function FormTeks() {
|
|||
|
||||
let id = Cookies.get("idCreate");
|
||||
|
||||
if (scheduleId !== undefined) {
|
||||
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||
}
|
||||
|
||||
if (id == undefined) {
|
||||
const response = await createMedia(requestData);
|
||||
console.log("Form Data Submitted:", requestData);
|
||||
|
|
|
|||
|
|
@ -441,7 +441,22 @@ export default function FormVideo() {
|
|||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||
return;
|
||||
}
|
||||
const requestData = {
|
||||
let requestData: {
|
||||
title: string;
|
||||
description: string;
|
||||
htmlDescription: string;
|
||||
fileTypeId: string;
|
||||
categoryId: any;
|
||||
subCategoryId: any;
|
||||
uploadedBy: string;
|
||||
statusId: string;
|
||||
publishedFor: string;
|
||||
creatorName: string;
|
||||
tags: string;
|
||||
isYoutube: boolean;
|
||||
isInternationalMedia: boolean;
|
||||
attachFromScheduleId?: number; // ✅ Tambahkan properti ini
|
||||
} = {
|
||||
...data,
|
||||
title: finalTitle,
|
||||
description: finalDescription,
|
||||
|
|
@ -460,6 +475,10 @@ export default function FormVideo() {
|
|||
|
||||
let id = Cookies.get("idCreate");
|
||||
|
||||
if (scheduleId !== undefined) {
|
||||
requestData.attachFromScheduleId = Number(scheduleId); // ✅ Tambahkan nilai ini
|
||||
}
|
||||
|
||||
if (id == undefined) {
|
||||
const response = await createMedia(requestData);
|
||||
console.log("Form Data Submitted:", requestData);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ export default function FormContestDetail() {
|
|||
mabes: false,
|
||||
polda: false,
|
||||
polres: false,
|
||||
satker: false,
|
||||
});
|
||||
|
||||
const {
|
||||
|
|
@ -224,18 +225,17 @@ export default function FormContestDetail() {
|
|||
}, [detail?.targetOutput]);
|
||||
|
||||
useEffect(() => {
|
||||
if (detail?.targetParticipantTopLevel) {
|
||||
const outputSet = new Set(
|
||||
detail.targetParticipantTopLevel.split(",").map(Number)
|
||||
);
|
||||
if (detail?.targetOutput) {
|
||||
const outputSet = new Set(detail.targetOutput.split(",").map(Number));
|
||||
setUnitSelection({
|
||||
allUnit: outputSet.has(0),
|
||||
mabes: outputSet.has(1),
|
||||
polda: outputSet.has(2),
|
||||
polres: outputSet.has(3),
|
||||
satker: outputSet.has(4),
|
||||
});
|
||||
}
|
||||
}, [detail?.targetParticipantTopLevel]);
|
||||
}, [detail?.targetOutput]);
|
||||
|
||||
const handleCheckboxChange = (levelId: number) => {
|
||||
setCheckedLevels((prev) => {
|
||||
|
|
@ -267,6 +267,7 @@ export default function FormContestDetail() {
|
|||
mabes: "1",
|
||||
polda: "2",
|
||||
polres: "3",
|
||||
satker: "4",
|
||||
};
|
||||
|
||||
const assignmentPurposeString = Object.keys(unitSelection)
|
||||
|
|
@ -436,7 +437,7 @@ export default function FormContestDetail() {
|
|||
fileTypeId: string,
|
||||
duration: string
|
||||
) {
|
||||
console.log(idx, id, file, fileTypeId, duration);
|
||||
console.log("Param Upload : ", idx, id, file, fileTypeId, duration);
|
||||
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.token;
|
||||
|
|
@ -451,7 +452,7 @@ export default function FormContestDetail() {
|
|||
retryDelays: [0, 3000, 6000, 12_000, 24_000],
|
||||
chunkSize: 20_000,
|
||||
metadata: {
|
||||
assignmentId: id,
|
||||
contestId: id,
|
||||
filename: file.name,
|
||||
contentType: file.type,
|
||||
fileTypeId: fileTypeId,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {
|
|||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CalendarIcon, Clock1, MapPin, Plus, User2 } from "lucide-react";
|
||||
import { CalendarIcon, Clock1, Eye, MapPin, Plus, User2 } from "lucide-react";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import { addDays, format, parseISO, setDate } from "date-fns";
|
||||
import { DateRange } from "react-day-picker";
|
||||
|
|
@ -30,6 +30,7 @@ import { error, loading } from "@/lib/swal";
|
|||
import Cookies from "js-cookie";
|
||||
import {
|
||||
detailSchedule,
|
||||
getListScheduleAttachment,
|
||||
listScheduleNext,
|
||||
listScheduleToday,
|
||||
postSchedule,
|
||||
|
|
@ -61,6 +62,14 @@ interface Detail {
|
|||
addressLong: number;
|
||||
}
|
||||
|
||||
interface Attachment {
|
||||
id: any;
|
||||
title: string;
|
||||
fileTypeId: number;
|
||||
type: number;
|
||||
fileTypeName: string;
|
||||
}
|
||||
|
||||
export default function FormEventDetail() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { id } = useParams() as { id: string };
|
||||
|
|
@ -89,6 +98,14 @@ export default function FormEventDetail() {
|
|||
},
|
||||
});
|
||||
|
||||
const [lampiran, setDataLampiran] = useState<Attachment[]>([]);
|
||||
|
||||
async function getDataAttachment() {
|
||||
const response = await getListScheduleAttachment(id);
|
||||
console.log("data attach", response?.data?.data?.content);
|
||||
setDataLampiran(response?.data?.data?.content);
|
||||
}
|
||||
|
||||
async function getDataByDate() {
|
||||
const resToday = await listScheduleToday();
|
||||
const today = resToday?.data?.data;
|
||||
|
|
@ -120,6 +137,7 @@ export default function FormEventDetail() {
|
|||
}
|
||||
}
|
||||
initState();
|
||||
getDataAttachment();
|
||||
}, [refresh, setValue]);
|
||||
|
||||
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
|
@ -130,6 +148,29 @@ export default function FormEventDetail() {
|
|||
setEndTime(e.target.value);
|
||||
};
|
||||
|
||||
const handleDestinationUpload = (
|
||||
type: number,
|
||||
id: string | number,
|
||||
setOpen: (open: boolean) => void,
|
||||
router: any
|
||||
) => {
|
||||
setOpen(false); // Tutup modal dialog
|
||||
|
||||
if (id !== undefined) {
|
||||
Cookies.set("scheduleId", id.toString(), { expires: 1 });
|
||||
Cookies.set("scheduleType", "3", { expires: 1 });
|
||||
|
||||
const routes: Record<number, string> = {
|
||||
1: "/in/contributor/schedule/media/image/create",
|
||||
2: "/in/contributor/schedule/media/video/create",
|
||||
3: "/in/contributor/schedule/media/text/create",
|
||||
4: "/in/contributor/schedule/media/audio/create",
|
||||
};
|
||||
|
||||
router.push(routes[type] || "/admin/schedule/media/audio/create");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row gap-2">
|
||||
<Card className="w-full lg:w-9/12">
|
||||
|
|
@ -336,92 +377,67 @@ export default function FormEventDetail() {
|
|||
<Button color="primary" size="sm" type="button">
|
||||
<Plus /> Tambah Lampiran
|
||||
</Button>
|
||||
<p>0 Lampiran</p>
|
||||
<p>{lampiran?.length || 0} Lampiran</p>
|
||||
</div>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
|
||||
<h2 className="text-lg font-semibold">
|
||||
Pilih Jenis Lampiran
|
||||
</h2>
|
||||
<div className=" space-y-4 gap-y-4">
|
||||
<Link href={"/contributor/schedule/media/video/create"}>
|
||||
<div className="space-y-4 gap-y-4">
|
||||
{[
|
||||
{
|
||||
type: 2,
|
||||
img: "/assets/img/upload-video.png",
|
||||
label: "Audio Visual",
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
img: "/assets/img/upload-image.png",
|
||||
label: "Foto",
|
||||
},
|
||||
{
|
||||
type: 3,
|
||||
img: "/assets/img/upload-text.png",
|
||||
label: "Teks",
|
||||
},
|
||||
{
|
||||
type: 4,
|
||||
img: "/assets/img/upload-audio.png",
|
||||
label: "Audio",
|
||||
},
|
||||
].map((item) => (
|
||||
<a
|
||||
key={item.type}
|
||||
onClick={() =>
|
||||
handleDestinationUpload(
|
||||
item.type,
|
||||
id,
|
||||
setOpen,
|
||||
router
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-video.png"}
|
||||
alt={"item.label"}
|
||||
src={item.img}
|
||||
alt={item.label}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">
|
||||
Audio Visual
|
||||
{item.label}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
Unggah media berupa {item.label.toLowerCase()}{" "}
|
||||
dengan format sesuai yang didukung.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={"/contributor/schedule/media/image/create"}>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-image.png"}
|
||||
alt={"item.label"}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">Foto</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={"/contributor/schedule/media/text/create"}>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-text.png"}
|
||||
alt={"item.label"}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">Teks</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={"/contributor/schedule/media/audio/create"}>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-audio.png"}
|
||||
alt={"item.label"}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">Audio</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
|
@ -430,7 +446,52 @@ export default function FormEventDetail() {
|
|||
""
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-4 flex justify-end">
|
||||
<div className="mt-6 mx-6">
|
||||
<table className="w-full border border-gray-300 rounded-lg">
|
||||
<thead className="bg-gray-200 text-left">
|
||||
<tr>
|
||||
<th className="p-3 font-semibold">Judul Konten</th>
|
||||
<th className="p-3 font-semibold">Konten</th>
|
||||
<th className="p-3 font-semibold">Tindakan</th>
|
||||
<th className="p-3 font-semibold">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{lampiran.map((item, index) => (
|
||||
<tr key={index} className="border-t border-gray-300">
|
||||
<td className="p-3 text-blue-600 cursor-pointer">
|
||||
{item.title}
|
||||
</td>
|
||||
<td className="p-3">{item.fileTypeName}</td>
|
||||
<td className="p-3 text-blue-600">Konfersi Ai</td>
|
||||
<td className="p-3">
|
||||
<Link
|
||||
href={
|
||||
Number(item.fileTypeId) == 1
|
||||
? `/contributor/content/image/detail/${item.id}`
|
||||
: Number(item.fileTypeId) == 2
|
||||
? `/contributor/content/video/detail/${item.id}`
|
||||
: Number(item.fileTypeId) == 3
|
||||
? `/contributor/content/teks/detail/${item.id}`
|
||||
: `/contributor/content/audio/detail/${item.id}`
|
||||
}
|
||||
target="_blank"
|
||||
className="btn"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Eye
|
||||
className={
|
||||
item.type === 1 ? "text-blue-600" : "text-black"
|
||||
}
|
||||
/>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="my-4 mr-6 flex justify-end">
|
||||
<Button type="submit" color="primary">
|
||||
Submit
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import {
|
|||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CalendarIcon, Clock1, MapPin, Plus, User2 } from "lucide-react";
|
||||
import { CalendarIcon, Clock1, Eye, MapPin, Plus, User2 } from "lucide-react";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
import { addDays, format, parseISO, setDate } from "date-fns";
|
||||
import { DateRange } from "react-day-picker";
|
||||
|
|
@ -30,6 +30,7 @@ import { error, loading } from "@/lib/swal";
|
|||
import Cookies from "js-cookie";
|
||||
import {
|
||||
detailSchedule,
|
||||
getListScheduleAttachment,
|
||||
listScheduleNext,
|
||||
listScheduleToday,
|
||||
postSchedule,
|
||||
|
|
@ -50,6 +51,7 @@ import {
|
|||
import { formatDate } from "@fullcalendar/core/index.js";
|
||||
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import $ from "jquery";
|
||||
|
||||
const taskSchema = z.object({
|
||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||
|
|
@ -68,6 +70,14 @@ interface Detail {
|
|||
addressLong: number;
|
||||
}
|
||||
|
||||
interface Attachment {
|
||||
id: any;
|
||||
title: string;
|
||||
fileTypeId: number;
|
||||
type: number;
|
||||
fileTypeName: string;
|
||||
}
|
||||
|
||||
export default function FormDetailPressRillis() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { id } = useParams() as { id: string };
|
||||
|
|
@ -98,6 +108,14 @@ export default function FormDetailPressRillis() {
|
|||
},
|
||||
});
|
||||
|
||||
const [lampiran, setDataLampiran] = useState<Attachment[]>([]);
|
||||
|
||||
async function getDataAttachment() {
|
||||
const response = await getListScheduleAttachment(id);
|
||||
console.log("data attach", response?.data?.data?.content);
|
||||
setDataLampiran(response?.data?.data?.content);
|
||||
}
|
||||
|
||||
async function getDataByDate() {
|
||||
const resToday = await listScheduleToday();
|
||||
const today = resToday?.data?.data;
|
||||
|
|
@ -129,6 +147,7 @@ export default function FormDetailPressRillis() {
|
|||
}
|
||||
}
|
||||
initState();
|
||||
getDataAttachment();
|
||||
}, [refresh, setValue]);
|
||||
|
||||
const handleStartTime = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
|
@ -139,20 +158,26 @@ export default function FormDetailPressRillis() {
|
|||
setEndTime(e.target.value);
|
||||
};
|
||||
|
||||
const handleUploadAttachment = () => {
|
||||
const scheduleId = Cookies.get("scheduleId");
|
||||
const handleDestinationUpload = (
|
||||
type: number,
|
||||
id: string | number,
|
||||
setOpen: (open: boolean) => void,
|
||||
router: any
|
||||
) => {
|
||||
setOpen(false); // Tutup modal dialog
|
||||
|
||||
if (scheduleId == undefined) {
|
||||
MySwal.fire({
|
||||
title: "Simpan Jadwal Terlebih Dahulu",
|
||||
icon: "info",
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "Ok",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (id !== undefined) {
|
||||
Cookies.set("scheduleId", id.toString(), { expires: 1 });
|
||||
Cookies.set("scheduleType", "3", { expires: 1 });
|
||||
|
||||
const routes: Record<number, string> = {
|
||||
1: "/in/contributor/schedule/media/image/create",
|
||||
2: "/in/contributor/schedule/media/video/create",
|
||||
3: "/in/contributor/schedule/media/text/create",
|
||||
4: "/in/contributor/schedule/media/audio/create",
|
||||
};
|
||||
|
||||
router.push(routes[type] || "/admin/schedule/media/audio/create");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -379,92 +404,67 @@ export default function FormDetailPressRillis() {
|
|||
<Button color="primary" size="sm" type="button">
|
||||
<Plus /> Tambah Lampiran
|
||||
</Button>
|
||||
<p>0 Lampiran</p>
|
||||
<p>{lampiran?.length || 0} Lampiran</p>
|
||||
</div>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-md p-6 bg-white rounded-lg shadow-lg h-[420px] w-[700px]">
|
||||
<h2 className="text-lg font-semibold">
|
||||
Pilih Jenis Lampiran
|
||||
</h2>
|
||||
<div className=" space-y-4 gap-y-4">
|
||||
<Link href={"/contributor/schedule/media/video/create"}>
|
||||
<div className="space-y-4 gap-y-4">
|
||||
{[
|
||||
{
|
||||
type: 2,
|
||||
img: "/assets/img/upload-video.png",
|
||||
label: "Audio Visual",
|
||||
},
|
||||
{
|
||||
type: 1,
|
||||
img: "/assets/img/upload-image.png",
|
||||
label: "Foto",
|
||||
},
|
||||
{
|
||||
type: 3,
|
||||
img: "/assets/img/upload-text.png",
|
||||
label: "Teks",
|
||||
},
|
||||
{
|
||||
type: 4,
|
||||
img: "/assets/img/upload-audio.png",
|
||||
label: "Audio",
|
||||
},
|
||||
].map((item) => (
|
||||
<a
|
||||
key={item.type}
|
||||
onClick={() =>
|
||||
handleDestinationUpload(
|
||||
item.type,
|
||||
id,
|
||||
setOpen,
|
||||
router
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-video.png"}
|
||||
alt={"item.label"}
|
||||
src={item.img}
|
||||
alt={item.label}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">
|
||||
Audio Visual
|
||||
{item.label}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
Unggah media berupa {item.label.toLowerCase()}{" "}
|
||||
dengan format sesuai yang didukung.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={"/contributor/schedule/media/image/create"}>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-image.png"}
|
||||
alt={"item.label"}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">Foto</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={"/contributor/schedule/media/text/create"}>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-text.png"}
|
||||
alt={"item.label"}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">Teks</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<Link href={"/contributor/schedule/media/audio/create"}>
|
||||
<div className="flex flex-row items-center space-x-4">
|
||||
<div className="flex flex-col w-4/12 items-center">
|
||||
<img
|
||||
src={"/assets/img/upload-audio.png"}
|
||||
alt={"item.label"}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<h3 className="text-base font-semibold">Audio</h3>
|
||||
</div>
|
||||
<div className="w-8/12">
|
||||
<p className="text-sm text-gray-600">
|
||||
Unggah media berupa video dengan format avi, wmv,
|
||||
atau mp4 dengan ukuran minimal 2mb dan maksimal
|
||||
500mb.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
|
@ -472,6 +472,51 @@ export default function FormDetailPressRillis() {
|
|||
) : (
|
||||
""
|
||||
)}
|
||||
<div className="mt-6">
|
||||
<table className="w-full border border-gray-300 rounded-lg">
|
||||
<thead className="bg-gray-200 text-left">
|
||||
<tr>
|
||||
<th className="p-3 font-semibold">Judul Konten</th>
|
||||
<th className="p-3 font-semibold">Konten</th>
|
||||
<th className="p-3 font-semibold">Tindakan</th>
|
||||
<th className="p-3 font-semibold">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{lampiran.map((item, index) => (
|
||||
<tr key={index} className="border-t border-gray-300">
|
||||
<td className="p-3 text-blue-600 cursor-pointer">
|
||||
{item.title}
|
||||
</td>
|
||||
<td className="p-3">{item.fileTypeName}</td>
|
||||
<td className="p-3 text-blue-600">Konfersi Ai</td>
|
||||
<td className="p-3">
|
||||
<Link
|
||||
href={
|
||||
Number(item.fileTypeId) == 1
|
||||
? `/contributor/content/image/detail/${item.id}`
|
||||
: Number(item.fileTypeId) == 2
|
||||
? `/contributor/content/video/detail/${item.id}`
|
||||
: Number(item.fileTypeId) == 3
|
||||
? `/contributor/content/teks/detail/${item.id}`
|
||||
: `/contributor/content/audio/detail/${item.id}`
|
||||
}
|
||||
target="_blank"
|
||||
className="btn"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Eye
|
||||
className={
|
||||
item.type === 1 ? "text-blue-600" : "text-black"
|
||||
}
|
||||
/>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-4 flex justify-end">
|
||||
<Button type="submit" color="primary">
|
||||
Submit
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ const Division = () => {
|
|||
<div className="mx-auto px-4 w-full">
|
||||
{/* Header */}
|
||||
{/* <Reveal> */}
|
||||
{/* <h2 className="text-center text-2xl font-bold text-gray-800 dark:text-white mb-4">
|
||||
{/* <h2 className="text-center text-2xl font-bold text-gray-800 dark:text-white mb-3">
|
||||
{pathname?.split("/")[1] == "in" ? (
|
||||
<>
|
||||
{t("coverageOnly")} <span className="text-[#bb3523]">{t("division")}</span>{" "}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,17 @@ import React, { useEffect } from "react";
|
|||
import DateRangePicker from "@/components/date-range-picker";
|
||||
import { usePathname } from "@/components/navigation";
|
||||
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "./ui/dialog";
|
||||
import { Button } from "./ui/button";
|
||||
import { Label } from "./ui/label";
|
||||
import { Input } from "./ui/input";
|
||||
|
||||
const PageTitle = ({
|
||||
title,
|
||||
|
|
@ -30,7 +41,35 @@ const PageTitle = ({
|
|||
<div className="text-2xl font-medium text-default-800 capitalize">
|
||||
Dashboard
|
||||
</div>
|
||||
<DateRangePicker />
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline">Download Report</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Download Report</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="w-full">
|
||||
<Label>Date</Label>
|
||||
<Input
|
||||
type="date"
|
||||
// value={dateFilter}
|
||||
// onChange={(e) => setDateFilter(e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="submit"
|
||||
// onClick={downloadReport}
|
||||
>
|
||||
Download
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -160,7 +160,8 @@ const LoginForm = () => {
|
|||
Number(profile?.data?.data?.roleId) == 10 ||
|
||||
Number(profile?.data?.data?.roleId) == 11 ||
|
||||
Number(profile?.data?.data?.roleId) == 12 ||
|
||||
Number(profile?.data?.data?.roleId) == 18
|
||||
Number(profile?.data?.data?.roleId) == 18 ||
|
||||
Number(profile?.data?.data?.roleId) == 19
|
||||
) {
|
||||
if (profile?.data?.data?.roleId === 18) {
|
||||
window.location.href = "/in/dashboard/executive";
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ const ProfileInfo = () => {
|
|||
<div className="text-sm font-medium capitalize lg:block hidden">
|
||||
{detail?.fullname}
|
||||
</div>
|
||||
<p className="text-xs">({detail?.fullname})</p>
|
||||
<p className="text-xs">({detail?.username})</p>
|
||||
</div>
|
||||
<span className="text-base me-2.5 lg:inline-block hidden">
|
||||
<Icon icon="heroicons-outline:chevron-down"></Icon>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,285 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { ChevronsUpDown, Check, CirclePlus } from 'lucide-react';
|
||||
|
||||
import { cn, getCookiesDecrypt } from "@/lib/utils"
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/components/ui/avatar"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
CommandSeparator,
|
||||
} from "@/components/ui/command"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
import { useConfig } from "@/hooks/use-config";
|
||||
import { useMediaQuery } from "@/hooks/use-media-query";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useMenuHoverConfig } from "@/hooks/use-menu-hover";
|
||||
import { getInfoProfile } from "@/service/auth";
|
||||
import { getUserRolePlacements, saveUserRolePlacements } from "@/service/management-user/management-user";
|
||||
|
||||
// var groups = [
|
||||
// {
|
||||
// label: "Wilayah Tugas",
|
||||
// teams: [],
|
||||
// },
|
||||
// ]
|
||||
|
||||
// type Team = (typeof groups)[number]["teams"][number]
|
||||
|
||||
type PopoverTriggerProps = React.ComponentPropsWithoutRef<typeof PopoverTrigger>
|
||||
|
||||
interface TeamSwitcherProps extends PopoverTriggerProps { }
|
||||
|
||||
const scaleVariants = {
|
||||
collapsed: { scale: 0.8 },
|
||||
expanded: { scale: 1 }
|
||||
};
|
||||
|
||||
export default function TeamWorkspaceSwitcher({ className }: TeamSwitcherProps) {
|
||||
const [config] = useConfig();
|
||||
const [hoverConfig] = useMenuHoverConfig();
|
||||
const { hovered } = hoverConfig;
|
||||
const [detail, setDetail] = React.useState<any>();
|
||||
const userId = getCookiesDecrypt("uie");
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [showNewTeamDialog, setShowNewTeamDialog] = React.useState(false);
|
||||
const [groups, setGroups] = React.useState<any>()
|
||||
const [selectedTeam, setSelectedTeam] = React.useState<any>({ label: "", value: "" });
|
||||
const isDesktop = useMediaQuery("(min-width: 1280px)")
|
||||
if (config.showSwitcher === false || config.sidebar === 'compact') return null
|
||||
|
||||
React.useEffect(() => {
|
||||
async function initState() {
|
||||
const response = await getInfoProfile();
|
||||
const details = response?.data?.data;
|
||||
|
||||
setDetail(details);
|
||||
console.log("data", details);
|
||||
}
|
||||
|
||||
async function getPlacement() {
|
||||
const response = await getUserRolePlacements(Number(userId));
|
||||
const data = response?.data?.data;
|
||||
|
||||
var placementArr: any[] = [];
|
||||
data?.forEach((row: any) => {
|
||||
placementArr.push({
|
||||
label: row.roleName + " | " + row.userLevelName,
|
||||
value: Number(row.id),
|
||||
});
|
||||
});
|
||||
const groupsTemp = [
|
||||
{
|
||||
label: "Wilayah Tugas",
|
||||
teams: placementArr,
|
||||
}
|
||||
];
|
||||
setGroups(groupsTemp);
|
||||
}
|
||||
|
||||
initState();
|
||||
getPlacement();
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<Dialog open={showNewTeamDialog} onOpenChange={setShowNewTeamDialog}>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
|
||||
|
||||
<PopoverTrigger asChild>
|
||||
|
||||
|
||||
|
||||
<motion.div
|
||||
key={(config.collapsed && !hovered) ? "collapsed" : "expanded"}
|
||||
initial={{ scale: 0.9 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ type: "spring", stiffness: 300, damping: 20 }}
|
||||
|
||||
|
||||
>
|
||||
{(config.collapsed && !hovered) ? <Button
|
||||
variant="outline"
|
||||
color="secondary"
|
||||
role="combobox"
|
||||
fullWidth
|
||||
aria-expanded={open}
|
||||
aria-label="Select a team"
|
||||
className={cn(" h-14 w-14 mx-auto p-0 md:p-0 dark:border-secondary ring-offset-sidebar", className)}
|
||||
>
|
||||
<Avatar className="">
|
||||
<AvatarImage
|
||||
height={24}
|
||||
width={24}
|
||||
// src={session?.user?.image as any}
|
||||
alt={selectedTeam.label}
|
||||
className="grayscale"
|
||||
/>
|
||||
|
||||
<AvatarFallback>{detail?.username}</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button> : <Button
|
||||
variant="outline"
|
||||
color="secondary"
|
||||
role="combobox"
|
||||
fullWidth
|
||||
aria-expanded={open}
|
||||
aria-label="Select a team"
|
||||
className={cn(" h-auto py-3 md:px-3 px-3 justify-start dark:border-secondary ring-offset-sidebar", className)}
|
||||
>
|
||||
<div className=" flex gap-2 flex-1 items-center">
|
||||
<Avatar className=" flex-none h-[38px] w-[38px]">
|
||||
{/* <AvatarImage
|
||||
height={38}
|
||||
width={38}
|
||||
// src={session?.user?.image as any}
|
||||
alt={selectedTeam.label}
|
||||
className="grayscale"
|
||||
/> */}
|
||||
|
||||
<AvatarFallback><p className="text-md uppercase">{detail?.username[0]}</p></AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="flex-1 text-start w-[100px]">
|
||||
|
||||
<div className=" text-sm font-semibold text-default-900">{detail?.username}</div>
|
||||
<div className=" text-xs font-normal text-default-500 dark:text-default-700 truncate ">{selectedTeam.label}</div>
|
||||
|
||||
</div>
|
||||
<div className="">
|
||||
<ChevronsUpDown className="ml-auto h-5 w-5 shrink-0 text-default-500 dark:text-default-700" />
|
||||
</div>
|
||||
</div>
|
||||
</Button>}
|
||||
</motion.div>
|
||||
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandList>
|
||||
<CommandInput placeholder="Search team..." className=" placeholder:text-xs" />
|
||||
<CommandEmpty>No team found.</CommandEmpty>
|
||||
{groups?.map((group: any) => (
|
||||
<CommandGroup key={group.label} heading={group.label}>
|
||||
{group.teams.map((team: any) => (
|
||||
<CommandItem
|
||||
key={team.value}
|
||||
onSelect={() => {
|
||||
setSelectedTeam(team)
|
||||
setOpen(false)
|
||||
}}
|
||||
className="text-sm font-normal"
|
||||
>
|
||||
|
||||
{team.label}
|
||||
<Check
|
||||
className={cn(
|
||||
"ml-auto h-4 w-4",
|
||||
selectedTeam.value === team.value
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
)}
|
||||
/>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
))}
|
||||
</CommandList>
|
||||
{/* <CommandSeparator /> */}
|
||||
{/* <CommandList>
|
||||
<CommandGroup>
|
||||
<DialogTrigger asChild>
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
setOpen(false)
|
||||
setShowNewTeamDialog(true)
|
||||
}}
|
||||
>
|
||||
<CirclePlus className="mr-2 h-5 w-5" />
|
||||
Create Team
|
||||
</CommandItem>
|
||||
</DialogTrigger>
|
||||
</CommandGroup>
|
||||
</CommandList> */}
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create team</DialogTitle>
|
||||
<DialogDescription>
|
||||
Add a new team to manage products and customers.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div>
|
||||
<div className="space-y-4 py-2 pb-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name">Team name</Label>
|
||||
<Input id="name" placeholder="Acme Inc." />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="plan">Subscription plan</Label>
|
||||
<Select>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select a plan" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="free">
|
||||
<span className="font-medium">Free</span> -{" "}
|
||||
<span className="text-muted-foreground">
|
||||
Trial for two weeks
|
||||
</span>
|
||||
</SelectItem>
|
||||
<SelectItem value="pro">
|
||||
<span className="font-medium">Pro</span> -{" "}
|
||||
<span className="text-muted-foreground">
|
||||
$9/month per user
|
||||
</span>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setShowNewTeamDialog(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="submit">Continue</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
import React from 'react'
|
||||
import { Ellipsis, LogOut } from "lucide-react";
|
||||
import { usePathname } from "@/components/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
||||
import { getMenuList } from "@/lib/menus";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import {
|
||||
|
|
@ -26,6 +26,7 @@ import Logo from '@/components/logo';
|
|||
import SidebarHoverToggle from '@/components/partials/sidebar/sidebar-hover-toggle';
|
||||
import { useMenuHoverConfig } from '@/hooks/use-menu-hover';
|
||||
import { useMediaQuery } from '@/hooks/use-media-query';
|
||||
import TeamWorkspaceSwitcher from '../common/team-workspace-switcher';
|
||||
|
||||
|
||||
export function MenuClassic({ }) {
|
||||
|
|
@ -36,7 +37,7 @@ export function MenuClassic({ }) {
|
|||
const direction = getLangDir(params?.locale ?? '');
|
||||
|
||||
const isDesktop = useMediaQuery('(min-width: 1280px)')
|
||||
|
||||
const userRoleId = getCookiesDecrypt("urie");
|
||||
|
||||
const menuList = getMenuList(pathname, t);
|
||||
const [config, setConfig] = useConfig()
|
||||
|
|
@ -71,17 +72,16 @@ export function MenuClassic({ }) {
|
|||
|
||||
|
||||
<ScrollArea className="[&>div>div[style]]:!block" dir={direction}>
|
||||
{/* {isDesktop && (
|
||||
{isDesktop && Number(userRoleId) == 19 ? (
|
||||
<div className={cn(' space-y-3 mt-6 ', {
|
||||
'px-4': !collapsed || hovered,
|
||||
'text-center': collapsed || !hovered
|
||||
})}>
|
||||
|
||||
<TeamSwitcher />
|
||||
<SearchBar />
|
||||
<TeamWorkspaceSwitcher />
|
||||
{/* <SearchBar /> */}
|
||||
</div>
|
||||
|
||||
)} */}
|
||||
) : ""}
|
||||
|
||||
<nav className="mt-4 h-full w-full">
|
||||
<ul className=" h-full flex flex-col min-h-[calc(100vh-48px-36px-16px-32px)] lg:min-h-[calc(100vh-32px-40px-32px)] items-start space-y-1 px-4">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default function PerformancePoldaViz() {
|
|||
? isInternational[0]
|
||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-top10?"
|
||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-ranking-polda?"
|
||||
: `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?`;
|
||||
: `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?polda-selected=${provState}&`;
|
||||
|
||||
const view2 =
|
||||
levelName == "MABES POLRI"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
"use client";
|
||||
import Cookies from "js-cookie";
|
||||
import { useEffect, useState } from "react";
|
||||
import { getCookiesDecrypt } from "@/lib/utils";
|
||||
import { generateTicket } from "@/service/tableau/tableau-service";
|
||||
import { Button } from "../ui/button";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function PerformanceSatkerViz() {
|
||||
const [hasMounted, setHasMounted] = useState(false);
|
||||
const t = useTranslations("AnalyticsDashboard");
|
||||
const levelName = getCookiesDecrypt("ulnae");
|
||||
const poldaState = Cookies.get("state");
|
||||
const provState = Cookies.get("state-prov");
|
||||
|
||||
const [ticket1, setTicket1] = useState("");
|
||||
const [ticket2, setTicket2] = useState("");
|
||||
const [ticket3, setTicket3] = useState("");
|
||||
const [ticket4, setTicket4] = useState("");
|
||||
const [isInternational, setIsInternational] = useState([false, false, false]);
|
||||
|
||||
const baseUrl = "https://db-mediahub.polri.go.id/";
|
||||
const url = "https://db-mediahub.polri.go.id/trusted/";
|
||||
|
||||
const view1 =
|
||||
levelName == "MABES POLRI"
|
||||
? isInternational[0]
|
||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-top10?"
|
||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev201/db-konten-top10?"
|
||||
: `/views/2023_09_db-ranking-polres-by-polda_rev100/db-ranking-by-polda?polda-selected=${provState}&`;
|
||||
|
||||
const param = ":embed=yes&:toolbar=yes&:iframeSizedToWindow=true";
|
||||
|
||||
useEffect(() => {
|
||||
async function initState() {
|
||||
const response1 = await generateTicket();
|
||||
setTicket1(response1?.data?.data);
|
||||
}
|
||||
|
||||
initState();
|
||||
}, [isInternational]);
|
||||
|
||||
// Hooks
|
||||
useEffect(() => {
|
||||
setHasMounted(true);
|
||||
}, []);
|
||||
|
||||
// Render
|
||||
if (!hasMounted) return null;
|
||||
|
||||
const handleInternational = (index: number, val: boolean) => {
|
||||
const updatedIsInternational = [...isInternational];
|
||||
|
||||
updatedIsInternational[index] = val;
|
||||
setIsInternational(updatedIsInternational);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2 bg-white rounded-lg p-3">
|
||||
<p className="text-lg">
|
||||
<b>
|
||||
{isInternational[0] ? "SATKER PERFORMANCE" : "POLFORMANCE SATKER"}
|
||||
</b>
|
||||
</p>
|
||||
<div className="my-5">
|
||||
{ticket1 == "" ? (
|
||||
<iframe
|
||||
src={`${baseUrl + view1 + param}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
frameBorder="0"
|
||||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${`${url + ticket1}/${view1}${param}`}`}
|
||||
width="100%"
|
||||
height="750"
|
||||
frameBorder="0"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { Router } from "next/router";
|
||||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ export function error(msg: string): void {
|
|||
});
|
||||
}
|
||||
|
||||
export function success(redirect: string): void {
|
||||
export function success(router: Router, redirect: string): void {
|
||||
MySwal.fire({
|
||||
title: '<p class="text-green-600 font-bold">Sukses</p>',
|
||||
icon: "success",
|
||||
|
|
@ -38,7 +39,7 @@ export function success(redirect: string): void {
|
|||
allowOutsideClick: false,
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = redirect;
|
||||
router.push(redirect);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
441
lib/menus.ts
441
lib/menus.ts
|
|
@ -260,6 +260,70 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "settings",
|
||||
menus: [
|
||||
{
|
||||
id: "settings",
|
||||
href: "/admin/settings",
|
||||
label: t("settings"),
|
||||
active: pathname.includes("/settinng"),
|
||||
icon: "material-symbols:settings",
|
||||
submenus: [
|
||||
{
|
||||
href: "/admin/settings/category",
|
||||
label: t("category"),
|
||||
active: pathname === "/admin/settings/category",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/tag",
|
||||
label: "Tag",
|
||||
active: pathname === "/admin/settings/tag",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/banner",
|
||||
label: "Banner",
|
||||
active: pathname === "/admin/settings/banner",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/feedback",
|
||||
label: "Feedback",
|
||||
active: pathname === "/admin/settings/feedback",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/faq",
|
||||
label: "FAQ",
|
||||
active: pathname === "/admin/settings/faq",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "https://nat-mediahub.polri.go.id/",
|
||||
label: "Mediahub 2022",
|
||||
active: pathname === "/admin/settings/mediahub-2022",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/privacy",
|
||||
label: t("privacy"),
|
||||
active: pathname === "/admin/settings/privacy",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// ===== MENU TEMPLATE DASHCODE =====
|
||||
// {
|
||||
// groupLabel: t("apps"),
|
||||
|
|
@ -1527,21 +1591,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
submenus: [
|
||||
{
|
||||
href: "/contributor/schedule/press-conference",
|
||||
label: "konferensi pers",
|
||||
label: t("press-conference"),
|
||||
active: pathname.includes("/schedule/press-conference"),
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/event",
|
||||
label: "event",
|
||||
label: t("event"),
|
||||
active: pathname.includes("/schedule/event"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/press-release",
|
||||
label: "pers rilis",
|
||||
label: t("press-release"),
|
||||
active: pathname.includes("/schedule/press-release"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
|
|
@ -1725,21 +1789,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
submenus: [
|
||||
{
|
||||
href: "/contributor/schedule/press-conference",
|
||||
label: "konferensi pers",
|
||||
label: t("press-conference"),
|
||||
active: pathname.includes("/schedule/press-conference"),
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/event",
|
||||
label: "event",
|
||||
label: t("event"),
|
||||
active: pathname.includes("/schedule/event"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/press-release",
|
||||
label: "pers rilis",
|
||||
label: t("press-release"),
|
||||
active: pathname.includes("/schedule/press-release"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
|
|
@ -1790,6 +1854,70 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "settings",
|
||||
menus: [
|
||||
{
|
||||
id: "settings",
|
||||
href: "/admin/settings",
|
||||
label: t("settings"),
|
||||
active: pathname.includes("/settinng"),
|
||||
icon: "material-symbols:settings",
|
||||
submenus: [
|
||||
{
|
||||
href: "/admin/settings/category",
|
||||
label: t("category"),
|
||||
active: pathname === "/admin/settings/category",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/tag",
|
||||
label: "Tag",
|
||||
active: pathname === "/admin/settings/tag",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/banner",
|
||||
label: "Banner",
|
||||
active: pathname === "/admin/settings/banner",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/feedback",
|
||||
label: "Feedback",
|
||||
active: pathname === "/admin/settings/feedback",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/faq",
|
||||
label: "FAQ",
|
||||
active: pathname === "/admin/settings/faq",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "https://nat-mediahub.polri.go.id/",
|
||||
label: "Mediahub 2022",
|
||||
active: pathname === "/admin/settings/mediahub-2022",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/privacy",
|
||||
label: t("privacy"),
|
||||
active: pathname === "/admin/settings/privacy",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
} else if (Number(userLevelId) == 761) {
|
||||
menusSelected = [
|
||||
|
|
@ -1891,7 +2019,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
submenus: [
|
||||
{
|
||||
href: "/contributor/schedule/press-conference",
|
||||
label: "konferensi pers",
|
||||
label: t("press-conference"),
|
||||
active: pathname.includes("/schedule/press-conference"),
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
|
|
@ -1905,7 +2033,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
{
|
||||
href: "/contributor/schedule/press-release",
|
||||
label: "pers rilis",
|
||||
label: t("press-release"),
|
||||
active: pathname.includes("/schedule/press-release"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
|
|
@ -2105,21 +2233,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
submenus: [
|
||||
{
|
||||
href: "/contributor/schedule/press-conference",
|
||||
label: "konferensi pers",
|
||||
label: t("press-conference"),
|
||||
active: pathname.includes("/schedule/press-conference"),
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/event",
|
||||
label: "event",
|
||||
label: t("event"),
|
||||
active: pathname.includes("/schedule/event"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/press-release",
|
||||
label: "pers rilis",
|
||||
label: t("press-release"),
|
||||
active: pathname.includes("/schedule/press-release"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
|
|
@ -2314,21 +2442,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
submenus: [
|
||||
{
|
||||
href: "/contributor/schedule/press-conference",
|
||||
label: "konferensi pers",
|
||||
label: t("press-conference"),
|
||||
active: pathname.includes("/schedule/press-conference"),
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/event",
|
||||
label: "event",
|
||||
label: t("event"),
|
||||
active: pathname.includes("/schedule/event"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/contributor/schedule/press-release",
|
||||
label: "pers rilis",
|
||||
label: t("press-release"),
|
||||
active: pathname.includes("/schedule/press-release"),
|
||||
icon: "heroicons:shopping-cart",
|
||||
children: [],
|
||||
|
|
@ -2533,7 +2661,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
],
|
||||
},
|
||||
];
|
||||
} else if (Number(roleId) == 11) {
|
||||
} else if (Number(roleId) == 11 || Number(roleId) == 19) {
|
||||
menusSelected = [
|
||||
{
|
||||
groupLabel: t("apps"),
|
||||
|
|
@ -2705,13 +2833,6 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
active: pathname.includes("/dashboard"),
|
||||
icon: "material-symbols:dashboard",
|
||||
submenus: [
|
||||
{
|
||||
href: "/dashboard",
|
||||
label: "Breakdown",
|
||||
active: pathname === "/dashboard",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/dashboard/executive",
|
||||
label: "Executive",
|
||||
|
|
@ -2719,24 +2840,31 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "agenda-setting",
|
||||
menus: [
|
||||
{
|
||||
id: "agenda-setting",
|
||||
href: "/contributor/agenda-setting",
|
||||
label: t("agenda-setting"),
|
||||
active: pathname.includes("/agenda-setting"),
|
||||
icon: "iconoir:journal-page",
|
||||
submenus: [],
|
||||
href: "/dashboard",
|
||||
label: "Breakdown",
|
||||
active: pathname === "/dashboard",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// groupLabel: "",
|
||||
// id: "agenda-setting",
|
||||
// menus: [
|
||||
// {
|
||||
// id: "agenda-setting",
|
||||
// href: "/contributor/agenda-setting",
|
||||
// label: t("agenda-setting"),
|
||||
// active: pathname.includes("/agenda-setting"),
|
||||
// icon: "iconoir:journal-page",
|
||||
// submenus: [],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "management-user",
|
||||
|
|
@ -3015,16 +3143,16 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
icon: "material-symbols:dashboard",
|
||||
submenus: [
|
||||
{
|
||||
href: "/dashboard",
|
||||
label: "Breakdown",
|
||||
active: pathname === "/dashboard",
|
||||
href: "/dashboard/executive",
|
||||
label: "Executive",
|
||||
active: pathname === "/dashboard/executive",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/dashboard/executive",
|
||||
label: "Executive",
|
||||
active: pathname === "/dashboard/executive",
|
||||
href: "/dashboard",
|
||||
label: "Breakdown",
|
||||
active: pathname === "/dashboard",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
|
|
@ -3074,20 +3202,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "agenda-setting",
|
||||
menus: [
|
||||
{
|
||||
id: "agenda-setting",
|
||||
href: "/contributor/agenda-setting",
|
||||
label: t("agenda-setting"),
|
||||
active: pathname.includes("/agenda-setting"),
|
||||
icon: "iconoir:journal-page",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// groupLabel: "",
|
||||
// id: "agenda-setting",
|
||||
// menus: [
|
||||
// {
|
||||
// id: "agenda-setting",
|
||||
// href: "/contributor/agenda-setting",
|
||||
// label: t("agenda-setting"),
|
||||
// active: pathname.includes("/agenda-setting"),
|
||||
// icon: "iconoir:journal-page",
|
||||
// submenus: [],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "performance-polres",
|
||||
|
|
@ -3159,35 +3287,70 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// groupLabel: "",
|
||||
// id: "settings",
|
||||
// menus: [
|
||||
// {
|
||||
// id: "settings",
|
||||
// href: "/admin/settings",
|
||||
// label: t("settings"),
|
||||
// active: pathname.includes("/settinng"),
|
||||
// icon: "material-symbols:settings",
|
||||
// submenus: [
|
||||
// {
|
||||
// href: "/admin/settings/category",
|
||||
// label: t("category"),
|
||||
// active: pathname === "/admin/settings/category",
|
||||
// icon: "heroicons:arrow-trending-up",
|
||||
// children: [],
|
||||
// },
|
||||
// {
|
||||
// href: "/admin/settings/tag",
|
||||
// label: "Tag",
|
||||
// active: pathname === "/admin/settings/tag",
|
||||
// icon: "heroicons:arrow-trending-up",
|
||||
// children: [],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "settings",
|
||||
menus: [
|
||||
{
|
||||
id: "settings",
|
||||
href: "/admin/settings",
|
||||
label: t("settings"),
|
||||
active: pathname.includes("/settinng"),
|
||||
icon: "material-symbols:settings",
|
||||
submenus: [
|
||||
{
|
||||
href: "/admin/settings/category",
|
||||
label: t("category"),
|
||||
active: pathname === "/admin/settings/category",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/tag",
|
||||
label: "Tag",
|
||||
active: pathname === "/admin/settings/tag",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/banner",
|
||||
label: "Banner",
|
||||
active: pathname === "/admin/settings/banner",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/feedback",
|
||||
label: "Feedback",
|
||||
active: pathname === "/admin/settings/feedback",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/faq",
|
||||
label: "FAQ",
|
||||
active: pathname === "/admin/settings/faq",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "https://nat-mediahub.polri.go.id/",
|
||||
label: "Mediahub 2022",
|
||||
active: pathname === "/admin/settings/mediahub-2022",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/privacy",
|
||||
label: t("privacy"),
|
||||
active: pathname === "/admin/settings/privacy",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
} else {
|
||||
menusSelected = [
|
||||
|
|
@ -3201,11 +3364,39 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
label: t("dashboard"),
|
||||
active: pathname.includes("/dashboard"),
|
||||
icon: "material-symbols:dashboard",
|
||||
submenus: [
|
||||
{
|
||||
href: "/dashboard/executive",
|
||||
label: "Executive",
|
||||
active: pathname === "/dashboard/executive",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/dashboard",
|
||||
label: "Breakdown",
|
||||
active: pathname === "/dashboard",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "management-user",
|
||||
menus: [
|
||||
{
|
||||
id: "management-user-menu",
|
||||
href: "/admin/management-user",
|
||||
label: "Management User",
|
||||
active: pathname.includes("/management-user"),
|
||||
icon: "clarity:users-solid",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "content-production",
|
||||
|
|
@ -3234,6 +3425,49 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "performance-polres",
|
||||
menus: [
|
||||
{
|
||||
id: "performance-polres",
|
||||
href: "/admin/performance-satker",
|
||||
label: t("performance-satker"),
|
||||
active: pathname.includes("/admin/performance-satker"),
|
||||
icon: "ant-design:signal-filled",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "media-tracking",
|
||||
menus: [
|
||||
{
|
||||
id: "media-tracking",
|
||||
href: "/curator/media-tracking",
|
||||
label: t("media-tracking"),
|
||||
active: pathname.includes("/media-tracking"),
|
||||
icon: "material-symbols:map-search-outline",
|
||||
submenus: [
|
||||
{
|
||||
href: "/admin/media-tracking/media-online",
|
||||
label: "Media Online",
|
||||
active: pathname === "/media-tracking/media-online",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/media-tracking/tb-news",
|
||||
label: "Tracking Beritra Hari Ini",
|
||||
active: pathname === "/media-tracking/news",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "communication",
|
||||
|
|
@ -3273,6 +3507,41 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/banner",
|
||||
label: "Banner",
|
||||
active: pathname === "/admin/settings/banner",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/feedback",
|
||||
label: "Feedback",
|
||||
active: pathname === "/admin/settings/feedback",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/faq",
|
||||
label: "FAQ",
|
||||
active: pathname === "/admin/settings/faq",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "https://nat-mediahub.polri.go.id/",
|
||||
label: "Mediahub 2022",
|
||||
active: pathname === "/admin/settings/mediahub-2022",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/admin/settings/privacy",
|
||||
label: t("privacy"),
|
||||
active: pathname === "/admin/settings/privacy",
|
||||
icon: "heroicons:arrow-trending-up",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -325,10 +325,15 @@
|
|||
"colors": "Colors",
|
||||
"performance-polda": "Performance Polda",
|
||||
"performance-polres": "Performance Polres",
|
||||
"performance-satker": "Performance Satker",
|
||||
"analysis": "Analysis",
|
||||
"management-content": "Content Management ",
|
||||
"add-experts": "Add Experts",
|
||||
"category": "Category",
|
||||
"add-category": "Add Category",
|
||||
"tags": "Tags",
|
||||
"add-tags": "Add Tags",
|
||||
"add": "Add",
|
||||
"privacy": "Privacy Policy"
|
||||
},
|
||||
"Changelog": {
|
||||
|
|
@ -580,7 +585,8 @@
|
|||
"schedule": "Schedule",
|
||||
"press-conference": "Press Conference",
|
||||
"press-release": "Press Release",
|
||||
"create-schedule": "Create Schedule"
|
||||
"create-schedule": "Create Schedule",
|
||||
"event": "event"
|
||||
},
|
||||
"Blog": {
|
||||
"table": "Table",
|
||||
|
|
@ -599,5 +605,37 @@
|
|||
"table": "Table",
|
||||
"contest": "Lomba",
|
||||
"create-contest": "Create Contest"
|
||||
},
|
||||
"Curation": {
|
||||
"content-curation": "Content Curation"
|
||||
},
|
||||
"Table": {
|
||||
"no": "No",
|
||||
"title": "Title",
|
||||
"category-name": "Category Name",
|
||||
"upload-date": "Upload Date",
|
||||
"creator-group": "Creator Group",
|
||||
"source": "source",
|
||||
"published": "Published",
|
||||
"date": "Date",
|
||||
"category": "Category",
|
||||
"tag": "Tag",
|
||||
"type-content": "Content Type",
|
||||
"type-task": "Task Type",
|
||||
"category-task": "Category Task",
|
||||
"code": "Code",
|
||||
"start-date": "Start Date",
|
||||
"end-date": "End Date",
|
||||
"speaker": "Speaker",
|
||||
"time": "Time",
|
||||
"address": "Address",
|
||||
"question": "Question",
|
||||
"sender": "Created By",
|
||||
"sendto": "SendTo",
|
||||
"type": "Type",
|
||||
"duration": "Duration",
|
||||
"target-output": "Target Output",
|
||||
"target-participant": "Target Participant",
|
||||
"action": "Actions"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,10 +326,15 @@
|
|||
"colors": "Colors",
|
||||
"performance-polda": "Performa Polda",
|
||||
"performance-polres": "Performa Polres",
|
||||
"performance-satker": "Performa Satker",
|
||||
"analysis": "Analisa",
|
||||
"management-content": "Manajemen Konten",
|
||||
"add-experts": "Tambah Tenaga Ahli",
|
||||
"category": "Kategori",
|
||||
"add-category": "Tambah Kategori",
|
||||
"tags": "Tag",
|
||||
"add-tags": "Tambah Tag",
|
||||
"add": "Tambah",
|
||||
"privacy": "Kebijakan Privacy"
|
||||
},
|
||||
"Changelog": {
|
||||
|
|
@ -581,7 +586,8 @@
|
|||
"schedule": "Jadwal",
|
||||
"press-conference": "Konferensi Pers",
|
||||
"press-release": "Pers Rilis",
|
||||
"create-schedule": "Buat Jadwal"
|
||||
"create-schedule": "Buat Jadwal",
|
||||
"event": "event"
|
||||
},
|
||||
"Blog": {
|
||||
"table": "Tabel",
|
||||
|
|
@ -600,5 +606,37 @@
|
|||
"table": "Tabel",
|
||||
"contest": "Lomba",
|
||||
"create-contest": "Buat Lomba"
|
||||
},
|
||||
"Curation": {
|
||||
"content-curation": "Kurasi Konten"
|
||||
},
|
||||
"Table": {
|
||||
"no": "Nomor",
|
||||
"title": "Judul",
|
||||
"category-name": "Nama Kategori",
|
||||
"upload-date": "Tanggal Upload",
|
||||
"creator-group": "Pembuat",
|
||||
"source": "Sumber",
|
||||
"published": "Diterbitkan",
|
||||
"date": "Tanggal",
|
||||
"category": "Kategori",
|
||||
"tag": "Tag",
|
||||
"type-content": "Tipe Konten",
|
||||
"type-task": "Tipen Penugasan",
|
||||
"category-task": "Kategori Penugasan",
|
||||
"code": "Kode",
|
||||
"start-date": "Tanggal Mulai",
|
||||
"end-date": "Tanggal Selesai",
|
||||
"speaker": "Disampaikan Oleh",
|
||||
"time": "Waktu",
|
||||
"address": "Alamat",
|
||||
"question": "Pertanyaan",
|
||||
"sender": "Pengirim",
|
||||
"sendto": "Penerima",
|
||||
"type": "Tipe",
|
||||
"duration": "Durasi",
|
||||
"target-output": "Target Output",
|
||||
"target-participant": "Target Peserta",
|
||||
"action": "Aksi"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 828 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
|
|
@ -129,10 +129,11 @@ export async function listSPIT(
|
|||
page: any,
|
||||
limit: any,
|
||||
title = "",
|
||||
contentCreatedDate = "",
|
||||
isPublish: any
|
||||
) {
|
||||
return await httpGetInterceptor(
|
||||
`media/spit/pagination?enablePage=1&page=${page}&size=${limit}&sort=desc&sortBy=contentTitleId&title=${title}&isPublish=${isPublish}`
|
||||
`media/spit/pagination?enablePage=1&page=${page}&size=${limit}&sort=desc&sortBy=contentTitleId&title=${title}& contentCreatedDate=${contentCreatedDate}&isPublish=${isPublish}`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +155,7 @@ export async function listEnableCategory(type: any) {
|
|||
}
|
||||
|
||||
export async function listCategory(type: any) {
|
||||
const url = `media/categories/list/publish?enablePage=0&sort=desc&sortBy=id&categoryId=${type}`;
|
||||
const url = `media/categories/list?enablePage=0&sort=desc&sortBy=id&categoryId=${type}`;
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
import {
|
||||
httpDeleteInterceptor,
|
||||
httpGetInterceptor,
|
||||
httpPostInterceptor,
|
||||
} from "../http-config/http-interceptor-service";
|
||||
|
||||
export async function listDataExperts(size: number, page: number) {
|
||||
return await httpGetInterceptor(
|
||||
`users/pagination/internal?enablePage=1&size=${size}&page=${page}&roleId=19&levelId=1`
|
||||
);
|
||||
}
|
||||
|
||||
export async function postBlog(data: any) {
|
||||
const url = "blog";
|
||||
return httpPostInterceptor(url, data);
|
||||
}
|
||||
|
||||
export async function getBlog(id: any) {
|
||||
const url = `blog/${id}`;
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import axios from "axios";
|
||||
|
||||
const baseURL = "https://mediahub.polri.go.id/api/";
|
||||
|
||||
const axiosBaseProdInstance = axios.create({
|
||||
baseURL,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
withCredentials: false,
|
||||
});
|
||||
|
||||
export default axiosBaseProdInstance;
|
||||
|
|
@ -17,7 +17,6 @@ const axiosInterceptorInstance = axios.create({
|
|||
// Request interceptor
|
||||
axiosInterceptorInstance.interceptors.request.use(
|
||||
(config) => {
|
||||
console.log("Config interceptor : ", config);
|
||||
const accessToken = Cookies.get("access_token");
|
||||
if (accessToken) {
|
||||
if (config.headers)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,171 @@
|
|||
import { useRouter } from "next/navigation";
|
||||
import Cookies from "js-cookie";
|
||||
import { getCsrfToken } from "../auth";
|
||||
import axiosBaseProdInstance from "./axios-base-prod-instance";
|
||||
|
||||
export async function httpGetInterceptor(pathUrl: any) {
|
||||
const pathname = window.location.pathname;
|
||||
const response = await axiosBaseProdInstance
|
||||
.get(pathUrl)
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else if (response?.status == 401) {
|
||||
Object.keys(Cookies.get()).forEach((cookieName) => {
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
if (
|
||||
pathname?.includes("/contributor/") ||
|
||||
pathname?.includes("/admin/") ||
|
||||
pathname?.includes("/supervisor/")
|
||||
) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpPostInterceptor(
|
||||
pathUrl: any,
|
||||
data?: any,
|
||||
headers?: any
|
||||
) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
};
|
||||
|
||||
const response = await axiosBaseProdInstance
|
||||
.post(pathUrl, data, { headers: mergedHeaders })
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else if (response?.status == 401) {
|
||||
Object.keys(Cookies.get()).forEach((cookieName) => {
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
window.location.href = "/";
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpPutInterceptor(
|
||||
pathUrl: any,
|
||||
data: any,
|
||||
headers?: any
|
||||
) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.token;
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...headers,
|
||||
};
|
||||
|
||||
const response = await axiosBaseProdInstance
|
||||
.put(pathUrl, data, { headers: mergedHeaders })
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else if (response?.status == 401) {
|
||||
Object.keys(Cookies.get()).forEach((cookieName) => {
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
window.location.href = "/";
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpDeleteInterceptor(pathUrl: any, data?: any) {
|
||||
const resCsrf = await getCsrfToken();
|
||||
const csrfToken = resCsrf?.data?.token;
|
||||
|
||||
const defaultHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const mergedHeaders = {
|
||||
...defaultHeaders,
|
||||
...(csrfToken ? { "X-XSRF-TOKEN": csrfToken } : {}),
|
||||
};
|
||||
|
||||
const response = await axiosBaseProdInstance
|
||||
.delete(pathUrl, { headers: mergedHeaders, data })
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else if (response?.status == 401) {
|
||||
Object.keys(Cookies.get()).forEach((cookieName) => {
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
window.location.href = "/";
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function httpGetInterceptorWithToken(pathUrl: any, headers?: any) {
|
||||
const response = await axiosBaseProdInstance
|
||||
.get(pathUrl, headers)
|
||||
.catch((error) => error.response);
|
||||
console.log("Response interceptor : ", response);
|
||||
if (response?.status == 200 || response?.status == 201) {
|
||||
return {
|
||||
error: false,
|
||||
message: "success",
|
||||
data: response?.data,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
error: true,
|
||||
message: response?.data?.message || response?.data || null,
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -30,16 +30,32 @@ export async function getListSchools() {
|
|||
const url = "users/user-schools/list";
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function getListCompetencies() {
|
||||
const url = "users/user-competencies/list";
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function getListExperiences() {
|
||||
const url = "users/user-experiences/list";
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function saveUserInternal(data: any) {
|
||||
const url = "users/save";
|
||||
return httpPostInterceptor(url, data);
|
||||
}
|
||||
|
||||
export async function saveUserRolePlacements(data: any) {
|
||||
const url = "users/role-placements";
|
||||
return httpPostInterceptor(url, data);
|
||||
}
|
||||
|
||||
export async function getUserRolePlacements(userId: number) {
|
||||
const url = `users/role-placements?userId=${userId}`;
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function getUserById(id: string) {
|
||||
const url = `users?id=${id}`;
|
||||
return httpGetInterceptor(url);
|
||||
|
|
|
|||
|
|
@ -5,8 +5,15 @@ import {
|
|||
import { httpGet } from "../http-config/http-base-service";
|
||||
import { any } from "zod";
|
||||
|
||||
export async function paginationSchedule(size: number, page: number, type: any, title: string = "") {
|
||||
return await httpGetInterceptor(`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`);
|
||||
export async function paginationSchedule(
|
||||
size: number,
|
||||
page: number,
|
||||
type: any,
|
||||
title: string = ""
|
||||
) {
|
||||
return await httpGetInterceptor(
|
||||
`schedule/pagination?enablePage=1&scheduleTypeId=${type}&page=${page}&size=${size}&title=${title}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function postSchedule(data: any) {
|
||||
|
|
@ -49,6 +56,11 @@ export async function listScheduleToday() {
|
|||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function getListScheduleAttachment(scheduleId: any) {
|
||||
const url = `media/list?&enablePage=0&scheduleId=${scheduleId}`;
|
||||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function listScheduleNext() {
|
||||
const url = "schedule/next-activity";
|
||||
return httpGetInterceptor(url);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { httpPostInterceptor } from "../http-config/http-interceptor-service";
|
||||
import { httpPostInterceptor } from "../http-config/http-interceptor-prod-service";
|
||||
|
||||
export async function generateTicket() {
|
||||
const url = "/admin/tableau-ticket";
|
||||
|
|
|
|||
Loading…
Reference in New Issue