Merge branch 'main' of https://gitlab.com/hanifsalafi/mediahub_redesign into dev-rama
This commit is contained in:
commit
73bd371fbc
|
|
@ -10,27 +10,7 @@ import {
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Link } from "@/components/navigation";
|
||||||
import {
|
|
||||||
formatDateToIndonesian,
|
|
||||||
getOnlyDate,
|
|
||||||
htmlToString,
|
|
||||||
} from "@/utils/globals";
|
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
import { Collapsible, CollapsibleContent } from "@/components/ui/collapsible";
|
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -47,24 +27,50 @@ const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "address",
|
accessorKey: "address",
|
||||||
header: "Wilayah",
|
header: "Wilayah",
|
||||||
cell: ({ row }) => <span>{row.getValue("address")}</span>,
|
cell: ({ row }) => <span>MABES</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "userRolePlacements",
|
||||||
|
header: "Posisi",
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const placements = row.original.userRolePlacements || [];
|
||||||
|
const placement = placements.find(
|
||||||
|
(p: any) => p.roleId === 11 || p.roleId === 12
|
||||||
|
);
|
||||||
|
|
||||||
|
let posisi = "-";
|
||||||
|
if (placement) {
|
||||||
|
posisi = placement.roleId === 11 ? "Koorkurator" : "Kurator";
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span>{posisi}</span>;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "role.name",
|
accessorKey: "role.name",
|
||||||
header: "Bidang Keahlian",
|
header: "Bidang Keahlian",
|
||||||
cell: ({ row }) => <span>{row.original.role?.name ?? "-"}</span>,
|
cell: ({ row }) => (
|
||||||
|
<span>
|
||||||
|
{row.original.userProfilesAdditional?.userCompetency?.name ?? "-"}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
accessorKey: "experience",
|
accessorKey: "userExperienceId",
|
||||||
header: "Pengalaman",
|
header: "Pengalaman",
|
||||||
cell: ({ row }) => <span>{row.getValue("experience")}</span>,
|
cell: ({ row }) => {
|
||||||
},
|
const experienceId =
|
||||||
|
row.original.userProfilesAdditional?.userExperienceId;
|
||||||
|
|
||||||
{
|
const experienceMap: Record<number, string> = {
|
||||||
accessorKey: "experience",
|
1: "Akademisi",
|
||||||
header: "Posisi",
|
2: "Praktisi",
|
||||||
cell: ({ row }) => <span>{row.getValue("experience")}</span>,
|
3: "Akademisi + Praktisi",
|
||||||
|
};
|
||||||
|
|
||||||
|
return <span>{experienceMap[experienceId] ?? "-"}</span>;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -84,8 +90,25 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<DropdownMenuContent className="p-0" align="end">
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
<Link href={`/admin/add-experts/detail/${row?.original?.id}`}>
|
||||||
<Link href="#">Detail</Link>
|
<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={`/admin/add-experts/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
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</Link>
|
||||||
|
<DropdownMenuItem
|
||||||
|
// onClick={() => handleDeleteMedia(row.original.id)}
|
||||||
|
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
||||||
|
>
|
||||||
|
<Trash2 className="w-4 h-4 me-1.5" />
|
||||||
|
Delete
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ export default function AddExpertForm() {
|
||||||
userCompetencyId: data.skills,
|
userCompetencyId: data.skills,
|
||||||
userExperienceId: data.experiences,
|
userExperienceId: data.experiences,
|
||||||
companyName: data.company,
|
companyName: data.company,
|
||||||
|
isAdmin: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
loading();
|
loading();
|
||||||
|
|
@ -272,8 +273,9 @@ export default function AddExpertForm() {
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Username</FormLabel>
|
<FormLabel>Username</FormLabel>
|
||||||
<Input
|
<Input
|
||||||
|
type="text"
|
||||||
value={field.value}
|
value={field.value}
|
||||||
placeholder="Masukkan Username"
|
placeholder="Masukkan"
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
@ -290,7 +292,7 @@ export default function AddExpertForm() {
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
value={field.value}
|
value={field.value}
|
||||||
placeholder="Masukkan Nama Lengkap"
|
placeholder="Masukkan No.Hp"
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
/>
|
/>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
@ -306,7 +308,7 @@ export default function AddExpertForm() {
|
||||||
<Input
|
<Input
|
||||||
type="email"
|
type="email"
|
||||||
value={field.value}
|
value={field.value}
|
||||||
placeholder="Masukkan Nama Lengkap"
|
placeholder="Masukkan email"
|
||||||
onChange={field.onChange}
|
onChange={field.onChange}
|
||||||
/>
|
/>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
@ -470,14 +472,14 @@ export default function AddExpertForm() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<Button
|
{/* <Button
|
||||||
type="button"
|
type="button"
|
||||||
size="md"
|
size="md"
|
||||||
onClick={handleAddRow}
|
onClick={handleAddRow}
|
||||||
disabled={placementRows.length >= 2} // optional: disable button if already 1 row added
|
disabled={placementRows.length >= 2} // optional: disable button if already 1 row added
|
||||||
>
|
>
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row justify-end gap-2 mt-4 pt-4">
|
<div className="flex flex-row justify-end gap-2 mt-4 pt-4">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
import FormDetailExperts from "@/components/form/experts/experts-detail";
|
||||||
|
|
||||||
|
const ExpertsDetailPage = async () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<FormDetailExperts />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExpertsDetailPage;
|
||||||
|
|
@ -0,0 +1,597 @@
|
||||||
|
"use client";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import withReactContent from "sweetalert2-react-content";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import { useRouter } from "@/i18n/routing";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import {
|
||||||
|
AdministrationLevelList,
|
||||||
|
getListCompetencies,
|
||||||
|
getListExperiences,
|
||||||
|
getUserById,
|
||||||
|
saveUserInternal,
|
||||||
|
saveUserRolePlacements,
|
||||||
|
} from "@/service/management-user/management-user";
|
||||||
|
import { loading } from "@/config/swal";
|
||||||
|
import { Eye, EyeOff } from "lucide-react";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
|
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",
|
||||||
|
}),
|
||||||
|
skills: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
experiences: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
company: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Placements = {
|
||||||
|
index: number;
|
||||||
|
roleId?: string;
|
||||||
|
userLevelId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Detail {
|
||||||
|
id: string;
|
||||||
|
fullname: string;
|
||||||
|
username: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
email: string;
|
||||||
|
birthPlace: string;
|
||||||
|
birthDate: string;
|
||||||
|
education: string;
|
||||||
|
career: string;
|
||||||
|
expertise: string;
|
||||||
|
experience: string;
|
||||||
|
position: string;
|
||||||
|
region: string;
|
||||||
|
cvUrl: string;
|
||||||
|
photoUrl: string;
|
||||||
|
isActive: boolean;
|
||||||
|
userProfilesAdditional?: {
|
||||||
|
companyName: string;
|
||||||
|
userExperienceId: any;
|
||||||
|
userCompetency?: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
isActive: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function UpdateExpertForm() {
|
||||||
|
const MySwal = withReactContent(Swal);
|
||||||
|
const router = useRouter();
|
||||||
|
const params = useParams();
|
||||||
|
const id = params?.id;
|
||||||
|
const [detail, setDetail] = useState<Detail | null>(null);
|
||||||
|
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 [passwordType, setPasswordType] = useState("password");
|
||||||
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDataAdditional();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function initState() {
|
||||||
|
if (id) {
|
||||||
|
const response = await getUserById(String(id));
|
||||||
|
const details = response?.data?.data;
|
||||||
|
setDetail(details);
|
||||||
|
}
|
||||||
|
if (detail?.userProfilesAdditional?.companyName) {
|
||||||
|
form.setValue("company", detail.userProfilesAdditional.companyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detail?.userProfilesAdditional?.userCompetency?.id) {
|
||||||
|
form.setValue(
|
||||||
|
"skills",
|
||||||
|
String(detail.userProfilesAdditional.userCompetency.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detail?.userProfilesAdditional?.userExperienceId) {
|
||||||
|
form.setValue(
|
||||||
|
"experiences",
|
||||||
|
String(detail.userProfilesAdditional.userExperienceId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initState();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
if (!detail) return <div>Loading...</div>;
|
||||||
|
|
||||||
|
const togglePasswordType = () => {
|
||||||
|
setPasswordType((prevType) =>
|
||||||
|
prevType === "password" ? "text" : "password"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const roleSelection = [
|
||||||
|
{
|
||||||
|
id: "11",
|
||||||
|
name: "Koor Kurator",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "12",
|
||||||
|
name: "Kurator",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||||
|
MySwal.fire({
|
||||||
|
title: "Simpan Data",
|
||||||
|
text: "Apakah Anda yakin ingin menyimpan data ini?",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
confirmButtonText: "Simpan",
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
save(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async (data: z.infer<typeof FormSchema>) => {
|
||||||
|
console.log("data", data);
|
||||||
|
|
||||||
|
const dataReq = {
|
||||||
|
id: detail?.id,
|
||||||
|
firstName: data.name,
|
||||||
|
username: data.username,
|
||||||
|
email: data.email,
|
||||||
|
password: data.password,
|
||||||
|
address: "",
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDataAdditional() {
|
||||||
|
const resCompetencies = await getListCompetencies();
|
||||||
|
setUserCompetencies(resCompetencies?.data?.data);
|
||||||
|
|
||||||
|
const resExperiences = await getListExperiences();
|
||||||
|
setUserExperiences(resExperiences?.data?.data);
|
||||||
|
console.log("experience", 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",
|
||||||
|
icon: "success",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
confirmButtonText: "OK",
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
router.push("/admin/add-experts");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = () => {
|
||||||
|
if (placementRows.length < 2) {
|
||||||
|
setPlacementRows((prevRows) => [
|
||||||
|
...prevRows,
|
||||||
|
{ index: incrementId, roleId: "", userLevelId: 0 },
|
||||||
|
]);
|
||||||
|
setIncrementId((prevId) => prevId + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
|
||||||
|
<Form {...form}>
|
||||||
|
{detail !== undefined ? (
|
||||||
|
<form
|
||||||
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
|
className="space-y-3 bg-white rounded-sm p-4"
|
||||||
|
>
|
||||||
|
<p className="fonnt-semibold">Campaign</p>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Nama Lengkap</FormLabel>
|
||||||
|
<Input
|
||||||
|
defaultValue={detail?.fullname}
|
||||||
|
placeholder="Masukkan Nama Lengkap"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="username"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Username</FormLabel>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
defaultValue={detail?.username}
|
||||||
|
placeholder="Masukkan"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="phoneNumber"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>No. HP</FormLabel>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
defaultValue={detail?.phoneNumber}
|
||||||
|
placeholder="Masukkan No.Hp"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="email"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Email</FormLabel>
|
||||||
|
<Input
|
||||||
|
type="email"
|
||||||
|
defaultValue={detail?.email}
|
||||||
|
placeholder="Masukkan email"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="password"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Password</FormLabel>
|
||||||
|
<div className="relative">
|
||||||
|
<Input
|
||||||
|
value={field.value}
|
||||||
|
type={showPassword ? "text" : "password"}
|
||||||
|
placeholder="Masukkan Password"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
className="absolute right-3 top-1/2 -translate-y-1/2 text-default-500 hover:text-default-700"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
|
{showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="skills"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Bidang Keahlian</FormLabel>
|
||||||
|
<Select onValueChange={field.onChange} value={field.value}>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={
|
||||||
|
detail?.userProfilesAdditional?.userCompetency?.name
|
||||||
|
? detail.userProfilesAdditional.userCompetency
|
||||||
|
.name
|
||||||
|
: "Pilih Bidang Keahlian"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{userCompetencies?.map((item: any) => (
|
||||||
|
<SelectItem key={item.id} value={String(item.id)}>
|
||||||
|
{item.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="experiences"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Pengalaman</FormLabel>
|
||||||
|
<Select onValueChange={field.onChange} value={field.value}>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={
|
||||||
|
detail &&
|
||||||
|
detail.userProfilesAdditional &&
|
||||||
|
detail.userProfilesAdditional.userExperienceId
|
||||||
|
? userExperiences?.find(
|
||||||
|
(item: any) =>
|
||||||
|
item.id ===
|
||||||
|
detail.userProfilesAdditional!
|
||||||
|
.userExperienceId
|
||||||
|
)?.name
|
||||||
|
: "Pilih Pengalaman"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
{userExperiences?.map((item: any) => (
|
||||||
|
<SelectItem key={item.id} value={String(item.id)}>
|
||||||
|
{item.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="company"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Nama Institusi/Perusahaan</FormLabel>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={detail?.userProfilesAdditional?.companyName || ""}
|
||||||
|
placeholder="Nama Institusi/Perusahaan"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<FormLabel>Posisi</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> */}
|
||||||
|
<Select
|
||||||
|
onValueChange={(e) =>
|
||||||
|
handleSelectionChange(row.index, "userLevelId", e)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Pilih User Level" />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="216">MABES POLRI</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}
|
||||||
|
disabled={placementRows.length >= 2} // optional: disable button if already 1 row added
|
||||||
|
>
|
||||||
|
Tambah
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-row justify-end gap-2 mt-4 pt-4">
|
||||||
|
<Button
|
||||||
|
size="md"
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
color="destructive"
|
||||||
|
className="text-xs"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="md"
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
className="text-xs"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -122,10 +122,22 @@ const useTableColumns = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<DropdownMenuContent className="p-0" align="end">
|
||||||
<DetailSettingTracking id={row.original.id} isDetail={true} />
|
<Link
|
||||||
|
href={`/admin/settings/setting-tracking/detail/${row.original.id}`}
|
||||||
<UpdateSettingTracking id={row.original.id} isUpdate={true} />
|
>
|
||||||
|
<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={`/admin/settings/setting-tracking/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
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</Link>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleDeleteMedia(row.original.id)}
|
onClick={() => handleDeleteMedia(row.original.id)}
|
||||||
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
||||||
|
|
|
||||||
|
|
@ -1,141 +1,141 @@
|
||||||
"use client";
|
// "use client";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
// import { Button } from "@/components/ui/button";
|
||||||
import {
|
// import {
|
||||||
Dialog,
|
// Dialog,
|
||||||
DialogContent,
|
// DialogContent,
|
||||||
DialogFooter,
|
// DialogFooter,
|
||||||
DialogHeader,
|
// DialogHeader,
|
||||||
DialogTitle,
|
// DialogTitle,
|
||||||
DialogTrigger,
|
// DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
// } from "@/components/ui/dialog";
|
||||||
import { z } from "zod";
|
// import { z } from "zod";
|
||||||
import { useForm } from "react-hook-form";
|
// import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
// import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import {
|
// import {
|
||||||
Form,
|
// Form,
|
||||||
FormControl,
|
// FormControl,
|
||||||
FormDescription,
|
// FormDescription,
|
||||||
FormField,
|
// FormField,
|
||||||
FormItem,
|
// FormItem,
|
||||||
FormLabel,
|
// FormLabel,
|
||||||
FormMessage,
|
// FormMessage,
|
||||||
} from "@/components/ui/form";
|
// } from "@/components/ui/form";
|
||||||
import { useRouter } from "@/i18n/routing";
|
// import { useRouter } from "@/i18n/routing";
|
||||||
import { Input } from "@/components/ui/input";
|
// import { Input } from "@/components/ui/input";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
// import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { getUserRoles, postCategory } from "@/service/settings/settings";
|
// import { getUserRoles, postCategory } from "@/service/settings/settings";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
// import { Fragment, useEffect, useState } from "react";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
// import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
// import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
// import { Textarea } from "@/components/ui/textarea";
|
||||||
import { close, error, loading } from "@/config/swal";
|
// import { close, error, loading } from "@/config/swal";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
// import { useToast } from "@/components/ui/use-toast";
|
||||||
import { stringify } from "querystring";
|
// import { stringify } from "querystring";
|
||||||
import { useDropzone } from "react-dropzone";
|
// import { useDropzone } from "react-dropzone";
|
||||||
import { CloudUpload } from "lucide-react";
|
// import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
// import Image from "next/image";
|
||||||
import { Upload } from "tus-js-client";
|
// import { Upload } from "tus-js-client";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
// import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import Cookies from "js-cookie";
|
// import Cookies from "js-cookie";
|
||||||
import { useTranslations } from "next-intl";
|
// import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const wilayahList = [
|
// const wilayahList = [
|
||||||
{ id: "mabes", label: "Mabes" },
|
// { id: "mabes", label: "Mabes" },
|
||||||
{ id: "polda", label: "Polda" },
|
// { id: "polda", label: "Polda" },
|
||||||
{ id: "satker", label: "Satker" },
|
// { id: "satker", label: "Satker" },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
const jumlahList = [5, 10, 15, 20, 25, 30];
|
// const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
export default function CreateSettingTracking() {
|
// export default function CreateSettingTracking() {
|
||||||
const t = useTranslations("Menu");
|
// const t = useTranslations("Menu");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
// const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const form = useForm({
|
// const form = useForm({
|
||||||
defaultValues: {
|
// defaultValues: {
|
||||||
wilayah: [] as string[],
|
// wilayah: [] as string[],
|
||||||
jumlah: [] as number[],
|
// jumlah: [] as number[],
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
|
|
||||||
const onSubmit = (values: any) => {
|
// const onSubmit = (values: any) => {
|
||||||
console.log("Submitted values:", values);
|
// console.log("Submitted values:", values);
|
||||||
setIsOpen(false);
|
// setIsOpen(false);
|
||||||
};
|
// };
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
// <Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
// <DialogTrigger asChild>
|
||||||
<Button onClick={() => setIsOpen(true)}>Tambah Setting Tracking</Button>
|
// <Button onClick={() => setIsOpen(true)}>Tambah Setting Tracking</Button>
|
||||||
</DialogTrigger>
|
// </DialogTrigger>
|
||||||
|
|
||||||
<DialogContent className="sm:max-w-md">
|
// <DialogContent className="sm:max-w-md">
|
||||||
<DialogHeader>
|
// <DialogHeader>
|
||||||
<DialogTitle>Add Setting Tracking Berita Harian</DialogTitle>
|
// <DialogTitle>Add Setting Tracking Berita Harian</DialogTitle>
|
||||||
</DialogHeader>
|
// </DialogHeader>
|
||||||
|
|
||||||
<Form {...form}>
|
// <Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
// <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
{/* Wilayah */}
|
// {/* Wilayah */}
|
||||||
<FormField
|
// <FormField
|
||||||
control={form.control}
|
// control={form.control}
|
||||||
name="wilayah"
|
// name="wilayah"
|
||||||
render={({ field }) => (
|
// render={({ field }) => (
|
||||||
<FormItem>
|
// <FormItem>
|
||||||
<FormLabel>Wilayah</FormLabel>
|
// <FormLabel>Wilayah</FormLabel>
|
||||||
<div className="flex gap-4">
|
// <div className="flex gap-4">
|
||||||
{wilayahList.map((item) => (
|
// {wilayahList.map((item) => (
|
||||||
<div key={item.id} className="flex items-center gap-2">
|
// <div key={item.id} className="flex items-center gap-2">
|
||||||
<Checkbox
|
// <Checkbox
|
||||||
checked={field.value.includes(item.id)}
|
// checked={field.value.includes(item.id)}
|
||||||
onCheckedChange={(checked) => {
|
// onCheckedChange={(checked) => {
|
||||||
const updated = checked
|
// const updated = checked
|
||||||
? [...field.value, item.id]
|
// ? [...field.value, item.id]
|
||||||
: field.value.filter((val) => val !== item.id);
|
// : field.value.filter((val) => val !== item.id);
|
||||||
field.onChange(updated);
|
// field.onChange(updated);
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
<label className="text-sm">{item.label}</label>
|
// <label className="text-sm">{item.label}</label>
|
||||||
</div>
|
// </div>
|
||||||
))}
|
// ))}
|
||||||
</div>
|
// </div>
|
||||||
</FormItem>
|
// </FormItem>
|
||||||
)}
|
// )}
|
||||||
/>
|
// />
|
||||||
|
|
||||||
<FormField
|
// <FormField
|
||||||
control={form.control}
|
// control={form.control}
|
||||||
name="jumlah"
|
// name="jumlah"
|
||||||
render={({ field }) => (
|
// render={({ field }) => (
|
||||||
<FormItem>
|
// <FormItem>
|
||||||
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
// <FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
<div className="flex gap-4 flex-wrap">
|
// <div className="flex gap-4 flex-wrap">
|
||||||
{jumlahList.map((num) => (
|
// {jumlahList.map((num) => (
|
||||||
<div key={num} className="flex items-center gap-2">
|
// <div key={num} className="flex items-center gap-2">
|
||||||
<Checkbox
|
// <Checkbox
|
||||||
checked={field.value.includes(num)}
|
// checked={field.value.includes(num)}
|
||||||
onCheckedChange={(checked) => {
|
// onCheckedChange={(checked) => {
|
||||||
const updated = checked
|
// const updated = checked
|
||||||
? [...field.value, num]
|
// ? [...field.value, num]
|
||||||
: field.value.filter((val) => val !== num);
|
// : field.value.filter((val) => val !== num);
|
||||||
field.onChange(updated);
|
// field.onChange(updated);
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
<label className="text-sm">{num}</label>
|
// <label className="text-sm">{num}</label>
|
||||||
</div>
|
// </div>
|
||||||
))}
|
// ))}
|
||||||
</div>
|
// </div>
|
||||||
</FormItem>
|
// </FormItem>
|
||||||
)}
|
// )}
|
||||||
/>
|
// />
|
||||||
|
|
||||||
<DialogFooter>
|
// <DialogFooter>
|
||||||
<Button type="submit">Tambah Setting</Button>
|
// <Button type="submit">Tambah Setting</Button>
|
||||||
</DialogFooter>
|
// </DialogFooter>
|
||||||
</form>
|
// </form>
|
||||||
</Form>
|
// </Form>
|
||||||
</DialogContent>
|
// </DialogContent>
|
||||||
</Dialog>
|
// </Dialog>
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,8 @@ import {
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import CreateSettingTracking from "./create";
|
|
||||||
import useTableColumns from "./column";
|
import useTableColumns from "./column";
|
||||||
|
import { UploadIcon } from "lucide-react";
|
||||||
|
|
||||||
const AdminSettingTrackingTable = () => {
|
const AdminSettingTrackingTable = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -190,7 +190,15 @@ const AdminSettingTrackingTable = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||||
<div className="flex items-end justify-between">
|
<div className="flex items-end justify-between">
|
||||||
<CreateSettingTracking />
|
{/* <CreateSettingTracking /> */}
|
||||||
|
<div className="flex-none">
|
||||||
|
<Link href={"/admin/settings/setting-tracking/create"}>
|
||||||
|
<Button color="primary" className="text-white" size="md">
|
||||||
|
<UploadIcon size={18} className="mr-2" />
|
||||||
|
Tambah Setting Tracking
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button size="md" variant="outline">
|
<Button size="md" variant="outline">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import CreateSettingTracking from "@/components/form/media-tracking/setting-tracking-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
const SettingTrackingCreatePage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<CreateSettingTracking />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingTrackingCreatePage;
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import DetailSettingTracking from "@/components/form/media-tracking/setting-tracking-detail-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
const SettingTrackingDetailPage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<DetailSettingTracking />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingTrackingDetailPage;
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import UpdateSettingTracking from "@/components/form/media-tracking/setting-tracking-update-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
const SettingTrackingUpdatePage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<UpdateSettingTracking />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingTrackingUpdatePage;
|
||||||
|
|
@ -52,7 +52,7 @@ import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||||
import { paginationBlog } from "@/service/blog/blog";
|
import { paginationBlog } from "@/service/blog/blog";
|
||||||
import { ticketingPagination } from "@/service/ticketing/ticketing";
|
import { ticketingPagination } from "@/service/ticketing/ticketing";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||||
import TablePagination from "@/components/table/table-pagination";
|
import TablePagination from "@/components/table/table-pagination";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -73,6 +73,9 @@ import useTableColumns from "./columns";
|
||||||
const TableImage = () => {
|
const TableImage = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
|
|
@ -199,7 +202,8 @@ const TableImage = () => {
|
||||||
formattedStartDate, // Pastikan format sesuai
|
formattedStartDate, // Pastikan format sesuai
|
||||||
formattedEndDate, // Pastikan format sesuai
|
formattedEndDate, // Pastikan format sesuai
|
||||||
search,
|
search,
|
||||||
filterByCreatorGroup
|
filterByCreatorGroup,
|
||||||
|
locale == "en"
|
||||||
);
|
);
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ const LiveReportTable = () => {
|
||||||
const res = await paginationSchedule(
|
const res = await paginationSchedule(
|
||||||
showData,
|
showData,
|
||||||
page - 1,
|
page - 1,
|
||||||
selectedType,
|
"",
|
||||||
search,
|
search,
|
||||||
statusFilter
|
statusFilter
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ const TaskTaPage = () => {
|
||||||
{t("tabel")} {t("task-ta")}
|
{t("tabel")} {t("task-ta")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-none">
|
<div className="flex-none">
|
||||||
{roleId !== 12 && roleId !== 19 && (
|
{roleId !== 12 && (
|
||||||
<Link href={"/contributor/task-ta/create"}>
|
<Link href={"/contributor/task-ta/create"}>
|
||||||
<Button color="primary" className="text-white">
|
<Button color="primary" className="text-white">
|
||||||
<UploadIcon size={18} className="mr-2" />
|
<UploadIcon size={18} className="mr-2" />
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export default function Questions() {
|
||||||
<Icon icon="ic:baseline-email" width={22} color="#2563eb" />
|
<Icon icon="ic:baseline-email" width={22} color="#2563eb" />
|
||||||
Email
|
Email
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
{/* <Link
|
||||||
href="/supervisor/communications/questions/facebook"
|
href="/supervisor/communications/questions/facebook"
|
||||||
className="flex items-center gap-3"
|
className="flex items-center gap-3"
|
||||||
>
|
>
|
||||||
|
|
@ -89,7 +89,7 @@ export default function Questions() {
|
||||||
color="#2563eb"
|
color="#2563eb"
|
||||||
/>
|
/>
|
||||||
Instagram
|
Instagram
|
||||||
</Link>
|
</Link> */}
|
||||||
<Link
|
<Link
|
||||||
href="/supervisor/communications/questions/whatsapp"
|
href="/supervisor/communications/questions/whatsapp"
|
||||||
className="flex items-center gap-3"
|
className="flex items-center gap-3"
|
||||||
|
|
@ -97,13 +97,13 @@ export default function Questions() {
|
||||||
<Icon icon="ri:whatsapp-fill" width={24} color="#2563eb" />
|
<Icon icon="ri:whatsapp-fill" width={24} color="#2563eb" />
|
||||||
Whatsapp
|
Whatsapp
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
{/* <Link
|
||||||
href="/supervisor/communications/questions/youtube"
|
href="/supervisor/communications/questions/youtube"
|
||||||
className="flex items-center gap-3"
|
className="flex items-center gap-3"
|
||||||
>
|
>
|
||||||
<Icon icon="mdi:youtube" width={24} color="#2563eb" />
|
<Icon icon="mdi:youtube" width={24} color="#2563eb" />
|
||||||
Youtube
|
Youtube
|
||||||
</Link>
|
</Link> */}
|
||||||
<Link
|
<Link
|
||||||
href="/supervisor/communications/questions/inbox"
|
href="/supervisor/communications/questions/inbox"
|
||||||
className="flex items-center gap-3"
|
className="flex items-center gap-3"
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { getHeroData, listData } from "@/service/landing/landing";
|
import { listData } from "@/service/landing/landing";
|
||||||
import { formatDateToIndonesian } from "@/utils/globals";
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { Link } from "@/i18n/routing";
|
import { Link } from "@/i18n/routing";
|
||||||
import { getHeroData, listCarousel, listData } from "@/service/landing/landing";
|
import { listData } from "@/service/landing/landing";
|
||||||
import { formatDateToIndonesian, textEllipsis } from "@/utils/globals";
|
import { formatDateToIndonesian, textEllipsis } from "@/utils/globals";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ const PopularNews = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
setHeroData(response?.data?.data?.content);
|
setHeroData(response?.data?.data?.content);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
import { getHeroData, listData } from "@/service/landing/landing";
|
import { listData } from "@/service/landing/landing";
|
||||||
import { formatDateToIndonesian } from "@/utils/globals";
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,30 @@ import React, { useEffect, useState } from "react";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { formatDateToIndonesian, getOnlyDate, getOnlyMonthAndYear } from "@/utils/globals";
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { getUserLevelListByParent, listCategory, listData, listDataRegional } from "@/service/landing/landing";
|
import {
|
||||||
import { ColumnDef, ColumnFiltersState, PaginationState, SortingState, VisibilityState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
getUserLevelListByParent,
|
||||||
|
listCategory,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
import LandingPagination from "@/components/landing-page/pagination";
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
|
@ -34,9 +54,14 @@ const FilterPage = () => {
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
[]
|
||||||
|
);
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
|
const [isFilterOpen, setIsFilterOpen] = useState(true);
|
||||||
|
|
||||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
|
|
@ -56,7 +81,9 @@ const FilterPage = () => {
|
||||||
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
||||||
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
const [searchTitle, setSearchTitle] = useState<string>("");
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
const [sortByOpt, setSortByOpt] = useState<any>(sortBy === "popular" ? "clickCount" : "createdAt");
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
const isRegional = asPath?.includes("regional");
|
const isRegional = asPath?.includes("regional");
|
||||||
const isSatker = asPath?.includes("satker");
|
const isSatker = asPath?.includes("satker");
|
||||||
const [formatFilter, setFormatFilter] = useState<any>([]);
|
const [formatFilter, setFormatFilter] = useState<any>([]);
|
||||||
|
|
@ -70,7 +97,7 @@ const FilterPage = () => {
|
||||||
const [userLevels, setUserLevels] = useState([]);
|
const [userLevels, setUserLevels] = useState([]);
|
||||||
const satkerName = params?.satker_name;
|
const satkerName = params?.satker_name;
|
||||||
let prefixPath = satkerName ? `/satker/${satkerName}` : "/";
|
let prefixPath = satkerName ? `/satker/${satkerName}` : "/";
|
||||||
|
|
||||||
const t = useTranslations("FilterPage");
|
const t = useTranslations("FilterPage");
|
||||||
|
|
||||||
// const [startDate, endDate] = dateRange;
|
// const [startDate, endDate] = dateRange;
|
||||||
|
|
@ -96,8 +123,14 @@ const FilterPage = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (categorie) {
|
if (categorie) {
|
||||||
setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
setCategoryFilter(
|
||||||
console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Kategori",
|
||||||
|
categorie,
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [categorie]);
|
}, [categorie]);
|
||||||
|
|
||||||
|
|
@ -115,7 +148,19 @@ const FilterPage = () => {
|
||||||
}
|
}
|
||||||
console.log(monthYearFilter, "monthFilter");
|
console.log(monthYearFilter, "monthFilter");
|
||||||
initState();
|
initState();
|
||||||
}, [change, asPath, monthYearFilter, page, sortBy, sortByOpt, title, startDateString, endDateString, categorie, formatFilter]);
|
}, [
|
||||||
|
change,
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
async function getCategories() {
|
async function getCategories() {
|
||||||
const category = await listCategory("1");
|
const category = await listCategory("1");
|
||||||
|
|
@ -137,7 +182,10 @@ const FilterPage = () => {
|
||||||
|
|
||||||
async function getDataAll() {
|
async function getDataAll() {
|
||||||
if (satkerName && String(satkerName)?.length > 1) {
|
if (satkerName && String(satkerName)?.length > 1) {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -155,8 +203,12 @@ const FilterPage = () => {
|
||||||
filterGroup,
|
filterGroup,
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : ""
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: ""
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
const data = response?.data?.data;
|
const data = response?.data?.data;
|
||||||
|
|
@ -166,7 +218,10 @@ const FilterPage = () => {
|
||||||
setTotalPage(data?.totalPages);
|
setTotalPage(data?.totalPages);
|
||||||
setTotalContent(response?.data?.data?.totalElements);
|
setTotalContent(response?.data?.data?.totalElements);
|
||||||
} else {
|
} else {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -183,8 +238,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : ""
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: ""
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
const data = response?.data?.data;
|
const data = response?.data?.data;
|
||||||
|
|
@ -231,7 +290,10 @@ const FilterPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDataRegional() {
|
async function getDataRegional() {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -244,8 +306,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
12,
|
12,
|
||||||
pages,
|
pages,
|
||||||
sortByOpt
|
sortByOpt
|
||||||
|
|
@ -362,114 +428,193 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Left */}
|
{/* Left */}
|
||||||
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
<div className="flex w-fit flex-col lg:flex-row gap-6 p-4">
|
||||||
<div className="lg:w-[25%] h-fit w-full bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="lg:hidden flex justify-end mb-2">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<button
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
onClick={() => setIsFilterOpen(!isFilterOpen)}
|
||||||
Filter
|
className="text-sm text-white bg-[#bb3523] px-4 py-1 rounded-md shadow"
|
||||||
</h2>
|
>
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
{isFilterOpen ? "Hide Filter" : "Show Filter"}
|
||||||
<div className="space-y-6">
|
</button>
|
||||||
<div>
|
</div>
|
||||||
<label htmlFor="search" className="block text-sm font-medium text-gray-700 dark:text-white">
|
{isFilterOpen && (
|
||||||
{t("search")}
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
</label>
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Input
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
value={searchTitle}
|
Filter
|
||||||
onChange={(e) => setSearchTitle(e.target.value)}
|
</h2>
|
||||||
onKeyUp={handleKeyUp}
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
onKeyDown={handleKeyDown}
|
<div className="space-y-6">
|
||||||
type="text"
|
<div>
|
||||||
id="search"
|
<label
|
||||||
placeholder={t("searchTitle")}
|
htmlFor="search"
|
||||||
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
/>
|
>
|
||||||
</div>
|
{t("search")}
|
||||||
|
</label>
|
||||||
<div>
|
<Input
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("monthYear")}</label>
|
value={searchTitle}
|
||||||
<ReactDatePicker
|
onChange={(e) => setSearchTitle(e.target.value)}
|
||||||
selected={monthYearFilter}
|
onKeyUp={handleKeyUp}
|
||||||
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
onKeyDown={handleKeyDown}
|
||||||
onChange={(date) => setMonthYearFilter(date)}
|
type="text"
|
||||||
dateFormat="MM | yyyy"
|
id="search"
|
||||||
placeholderText={t("selectYear")}
|
placeholder={t("searchTitle")}
|
||||||
showMonthYearPicker
|
className="mt-1 w-full border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("date")}</label>
|
|
||||||
<div className="flex flex-row justify justify-between gap-2">
|
|
||||||
<ReactDatePicker
|
|
||||||
selectsRange
|
|
||||||
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
|
||||||
startDate={dateRange[0]}
|
|
||||||
endDate={dateRange[1]}
|
|
||||||
onChange={(update) => {
|
|
||||||
setDateRange(update);
|
|
||||||
}}
|
|
||||||
placeholderText={t("selectDate")}
|
|
||||||
onCalendarClose={() => setCalenderState(!calenderState)}
|
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center">{handleClose ? <Icon icon="carbon:close-filled" onClick={handleDeleteDate} width="20" inline color="#216ba5" /> : ""}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">{t("categories")}</h3>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
<ul className="mt-2 space-y-2">
|
{t("monthYear")}
|
||||||
{categories.map((category: any) => (
|
</label>
|
||||||
<li key={category?.id}>
|
<ReactDatePicker
|
||||||
<label className="inline-flex items-center" htmlFor={`${category.id}`}>
|
selected={monthYearFilter}
|
||||||
<Checkbox id={`${category.id}`} value={category.id} checked={categoryFilter.includes(String(category.id))} onCheckedChange={(e) => handleCategoryFilter(Boolean(e), category.id)} />
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">{category?.name}</span>
|
onChange={(date) => setMonthYearFilter(date)}
|
||||||
|
dateFormat="MM | yyyy"
|
||||||
|
placeholderText={t("selectYear")}
|
||||||
|
showMonthYearPicker
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date")}
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
className="mt-1 w-full border text-sm rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
startDate={dateRange[0]}
|
||||||
|
endDate={dateRange[1]}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update);
|
||||||
|
}}
|
||||||
|
placeholderText={t("selectDate")}
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories")}
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
{categories.map((category: any) => (
|
||||||
|
<li key={category?.id}>
|
||||||
|
<label
|
||||||
|
className="inline-flex items-center"
|
||||||
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
|
{/* Garis */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
|
<ul className="mt-2 space-y-2">
|
||||||
|
<li>
|
||||||
|
<label className="inline-flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("png")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "png")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PNG
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
<li>
|
||||||
</ul>
|
<label className="inline-flex items-center">
|
||||||
</div>
|
<Checkbox
|
||||||
{/* Garis */}
|
id="jpeg"
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
value="jpeg"
|
||||||
{/* Garis */}
|
checked={formatFilter.includes("jpeg")}
|
||||||
<div>
|
onCheckedChange={(e) =>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">Format</h3>
|
handleFormatFilter(Boolean(e), "jpeg")
|
||||||
<ul className="mt-2 space-y-2">
|
}
|
||||||
<li>
|
/>
|
||||||
<label className="inline-flex items-center">
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
<Checkbox id="png" value="png" checked={formatFilter.includes("png")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "png")} />
|
JPEG
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">PNG</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="jpeg" value="jpeg" checked={formatFilter.includes("jpeg")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "jpeg")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">JPEG</span>
|
id="jpg"
|
||||||
</label>
|
value="jpg"
|
||||||
</li>
|
checked={formatFilter.includes("jpg")}
|
||||||
<li>
|
onCheckedChange={(e) =>
|
||||||
<label className="inline-flex items-center">
|
handleFormatFilter(Boolean(e), "jpg")
|
||||||
<Checkbox id="jpg" value="jpg" checked={formatFilter.includes("jpg")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "jpg")} />
|
}
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">JPG</span>
|
/>
|
||||||
</label>
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
</li>
|
JPG
|
||||||
</ul>
|
</span>
|
||||||
</div>
|
</label>
|
||||||
<div className="border-t border-black dark:border-white my-4"></div>
|
</li>
|
||||||
<div className="text-center">
|
</ul>
|
||||||
<a onClick={cleanCheckbox} className="text-[#bb3523] cursor-pointer">
|
</div>
|
||||||
<b>Reset Filter</b>
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
</a>
|
<div className="text-center">
|
||||||
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
|
<b>Reset Filter</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
{/* Konten Kanan */}
|
{/* Konten Kanan */}
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex flex-col items-end mb-4">
|
<div className="flex flex-col items-end mb-4">
|
||||||
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
||||||
<select defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} onChange={(e) => handleSorting(e)} className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500">
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
|
||||||
|
onChange={(e) => handleSorting(e)}
|
||||||
|
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
>
|
||||||
<option value="latest">{t("latest")}</option>
|
<option value="latest">{t("latest")}</option>
|
||||||
<option value="popular">{t("mostPopular")}</option>
|
<option value="popular">{t("mostPopular")}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -478,21 +623,36 @@ const FilterPage = () => {
|
||||||
{imageData?.length > 0 ? (
|
{imageData?.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{imageData?.map((image: any) => (
|
{imageData?.map((image: any) => (
|
||||||
<Card key={image?.id} className="hover:scale-110 transition-transform duration-300">
|
<Card
|
||||||
|
key={image?.id}
|
||||||
|
className="hover:scale-110 transition-transform duration-300"
|
||||||
|
>
|
||||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||||
<Link href={`${prefixPath}/image/detail/${image?.slug}`}>
|
<Link href={`${prefixPath}/image/detail/${image?.slug}`}>
|
||||||
<img src={image?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" />
|
<img
|
||||||
|
src={image?.thumbnailLink}
|
||||||
|
className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center"
|
||||||
|
/>
|
||||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
|
<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" />
|
{formatDateToIndonesian(new Date(image?.createdAt))}{" "}
|
||||||
|
{image?.timezone ? image?.timezone : "WIB"}|{" "}
|
||||||
|
<Icon icon="formkit:eye" width="15" height="15" />
|
||||||
{image?.clickCount}{" "}
|
{image?.clickCount}{" "}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20">
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
fill="#f00"
|
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"
|
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"
|
||||||
/>
|
/>
|
||||||
</svg>{" "}
|
</svg>{" "}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{image?.title}</div>
|
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||||
|
{image?.title}
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -500,11 +660,19 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center text-black">
|
<p className="flex items-center justify-center text-black">
|
||||||
<img src="/assets/empty-data.png" alt="empty" className="h-60 w-60 my-4" />
|
<img
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
className="h-60 w-60 my-4"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<LandingPagination table={table} totalData={totalData} totalPage={totalPage} />
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,31 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { formatDateToIndonesian, getOnlyDate, getOnlyMonthAndYear, secondToTimes } from "@/utils/globals";
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
secondToTimes,
|
||||||
|
} from "@/utils/globals";
|
||||||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { getUserLevelListByParent, listCategory, listData, listDataRegional } from "@/service/landing/landing";
|
import {
|
||||||
import { ColumnDef, ColumnFiltersState, PaginationState, SortingState, VisibilityState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
getUserLevelListByParent,
|
||||||
|
listCategory,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
import LandingPagination from "@/components/landing-page/pagination";
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
@ -34,8 +55,11 @@ const FilterPage = () => {
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
[]
|
||||||
|
);
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
|
|
@ -56,7 +80,9 @@ const FilterPage = () => {
|
||||||
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
||||||
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
const [searchTitle, setSearchTitle] = useState<string>("");
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
const [sortByOpt, setSortByOpt] = useState<any>(sortBy === "popular" ? "clickCount" : "createdAt");
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
const isRegional = asPath?.includes("regional");
|
const isRegional = asPath?.includes("regional");
|
||||||
const isSatker = asPath?.includes("satker");
|
const isSatker = asPath?.includes("satker");
|
||||||
const [formatFilter, setFormatFilter] = useState<any>([]);
|
const [formatFilter, setFormatFilter] = useState<any>([]);
|
||||||
|
|
@ -102,8 +128,14 @@ const FilterPage = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (categorie) {
|
if (categorie) {
|
||||||
setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
setCategoryFilter(
|
||||||
console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Kategori",
|
||||||
|
categorie,
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [categorie]);
|
}, [categorie]);
|
||||||
|
|
||||||
|
|
@ -121,7 +153,19 @@ const FilterPage = () => {
|
||||||
}
|
}
|
||||||
console.log(monthYearFilter, "monthFilter");
|
console.log(monthYearFilter, "monthFilter");
|
||||||
initState();
|
initState();
|
||||||
}, [change, asPath, monthYearFilter, page, sortBy, sortByOpt, title, startDateString, endDateString, categorie, formatFilter]);
|
}, [
|
||||||
|
change,
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
async function getCategories() {
|
async function getCategories() {
|
||||||
const category = await listCategory("4");
|
const category = await listCategory("4");
|
||||||
|
|
@ -144,7 +188,10 @@ const FilterPage = () => {
|
||||||
async function getDataAll() {
|
async function getDataAll() {
|
||||||
if (asPath?.includes("/polda/") == true) {
|
if (asPath?.includes("/polda/") == true) {
|
||||||
if (asPath?.split("/")[2] !== "[polda_name]") {
|
if (asPath?.split("/")[2] !== "[polda_name]") {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -162,8 +209,14 @@ const FilterPage = () => {
|
||||||
filterGroup,
|
filterGroup,
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)
|
||||||
|
?.split("/")[0]
|
||||||
|
?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -178,7 +231,10 @@ const FilterPage = () => {
|
||||||
setTotalContent(response?.data?.data?.totalElements);
|
setTotalContent(response?.data?.data?.totalElements);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -195,8 +251,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -247,7 +307,10 @@ const FilterPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDataRegional() {
|
async function getDataRegional() {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -260,8 +323,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
12,
|
12,
|
||||||
pages,
|
pages,
|
||||||
sortByOpt
|
sortByOpt
|
||||||
|
|
@ -379,7 +446,7 @@ const FilterPage = () => {
|
||||||
|
|
||||||
{/* Left */}
|
{/* Left */}
|
||||||
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
||||||
<div className="lg:w-[25%] w-full bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
Filter
|
Filter
|
||||||
|
|
@ -387,7 +454,10 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="search" className="block text-sm font-medium text-gray-700 dark:text-white">
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
{t("search")}
|
{t("search")}
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -403,7 +473,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("monthYear")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear")}
|
||||||
|
</label>
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selected={monthYearFilter}
|
selected={monthYearFilter}
|
||||||
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
|
@ -415,7 +487,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("date")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date")}
|
||||||
|
</label>
|
||||||
<div className="flex flex-row justify justify-between gap-2">
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selectsRange
|
selectsRange
|
||||||
|
|
@ -428,18 +502,44 @@ const FilterPage = () => {
|
||||||
placeholderText={t("searchDate")}
|
placeholderText={t("searchDate")}
|
||||||
onCalendarClose={() => setCalenderState(!calenderState)}
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center">{handleClose ? <Icon icon="carbon:close-filled" onClick={handleDeleteDate} width="20" inline color="#216ba5" /> : ""}</div>
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">{t("categories")}</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories")}
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
{categories?.map((category: any) => (
|
{categories?.map((category: any) => (
|
||||||
<li key={category?.id}>
|
<li key={category?.id}>
|
||||||
<label className="inline-flex items-center" htmlFor={`${category.id}`}>
|
<label
|
||||||
<Checkbox id={`${category.id}`} value={category.id} checked={categoryFilter.includes(String(category.id))} onCheckedChange={(e) => handleCategoryFilter(Boolean(e), category.id)} />
|
className="inline-flex items-center"
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">{category?.name}</span>
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -449,25 +549,48 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
{/* Garis */}
|
{/* Garis */}
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">Format</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="png" value="png" checked={formatFilter.includes("wav")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "wav")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">WAV</span>
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("wav")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "wav")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
WAV
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="jpeg" value="jpeg" checked={formatFilter.includes("mp3")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "mp3")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">MP3</span>
|
id="jpeg"
|
||||||
|
value="jpeg"
|
||||||
|
checked={formatFilter.includes("mp3")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mp3")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MP3
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-black dark:border-white my-4"></div>
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<a onClick={cleanCheckbox} className="text-[#bb3523] cursor-pointer">
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
<b>Reset Filter</b>
|
<b>Reset Filter</b>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -479,7 +602,11 @@ const FilterPage = () => {
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex flex-col items-end mb-4">
|
<div className="flex flex-col items-end mb-4">
|
||||||
<h2 className="text-lg font-semibold">{t("sortBy")} </h2>
|
<h2 className="text-lg font-semibold">{t("sortBy")} </h2>
|
||||||
<select defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} onChange={(e) => handleSorting(e)} className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500">
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
|
||||||
|
onChange={(e) => handleSorting(e)}
|
||||||
|
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
>
|
||||||
<option value="latest">{t("latest")}</option>
|
<option value="latest">{t("latest")}</option>
|
||||||
<option value="popular">{t("mostPopular")}</option>
|
<option value="popular">{t("mostPopular")}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -502,11 +629,20 @@ const FilterPage = () => {
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
{audioData?.map((audio: any) => (
|
{audioData?.map((audio: any) => (
|
||||||
<div key={audio?.id}>
|
<div key={audio?.id}>
|
||||||
<Link href={`/audio/detail/${audio?.slug}`} className="flex flex-row items-center bg-white dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full">
|
<Link
|
||||||
|
href={`/audio/detail/${audio?.slug}`}
|
||||||
|
className="flex flex-row items-center bg-white dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full"
|
||||||
|
>
|
||||||
<div className="flex justify-center lg:justify-between w-full gap-2 lg:gap-6">
|
<div className="flex justify-center lg:justify-between w-full gap-2 lg:gap-6">
|
||||||
<div className="flex flex-row gap-3">
|
<div className="flex flex-row gap-3">
|
||||||
<div className="flex items-center justify-center bg-red-500 text-white rounded-lg w-16 h-full lg:h-16">
|
<div className="flex items-center justify-center bg-red-500 text-white rounded-lg w-16 h-full lg:h-16">
|
||||||
<svg width="32" height="34" viewBox="0 0 32 34" fill="null" xmlns="http://www.w3.org/2000/svg">
|
<svg
|
||||||
|
width="32"
|
||||||
|
height="34"
|
||||||
|
viewBox="0 0 32 34"
|
||||||
|
fill="null"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M23.404 0.452014C23.7033 0.35857 24.0204 0.336816 24.3297 0.388509C24.639 0.440203 24.9318 0.563895 25.1845 0.749599C25.4371 0.935304 25.6426 1.17782 25.7843 1.45756C25.9259 1.73731 25.9998 2.04644 26 2.36001V14.414C25.3462 14.2296 24.6766 14.1064 24 14.046V8.36001L10 12.736V27C10 28.1264 9.6197 29.2197 8.92071 30.1029C8.22172 30.9861 7.24499 31.6075 6.14877 31.8663C5.05255 32.125 3.90107 32.0061 2.88089 31.5287C1.86071 31.0514 1.03159 30.2435 0.52787 29.2361C0.024152 28.2286 -0.124656 27.0806 0.105556 25.9781C0.335768 24.8755 0.931513 23.883 1.79627 23.1613C2.66102 22.4396 3.74413 22.031 4.87009 22.0017C5.99606 21.9724 7.09893 22.3242 8.00001 23V6.73601C7.99982 6.30956 8.13596 5.8942 8.38854 5.55059C8.64112 5.20698 8.99692 4.9531 9.40401 4.82601L23.404 0.452014ZM10 10.64L24 6.26601V2.36001L10 6.73601V10.64ZM5.00001 24C4.20436 24 3.44129 24.3161 2.87869 24.8787C2.31608 25.4413 2.00001 26.2044 2.00001 27C2.00001 27.7957 2.31608 28.5587 2.87869 29.1213C3.44129 29.6839 4.20436 30 5.00001 30C5.79566 30 6.55872 29.6839 7.12133 29.1213C7.68394 28.5587 8.00001 27.7957 8.00001 27C8.00001 26.2044 7.68394 25.4413 7.12133 24.8787C6.55872 24.3161 5.79566 24 5.00001 24ZM32 25C32 27.387 31.0518 29.6761 29.364 31.364C27.6761 33.0518 25.387 34 23 34C20.6131 34 18.3239 33.0518 16.636 31.364C14.9482 29.6761 14 27.387 14 25C14 22.6131 14.9482 20.3239 16.636 18.6361C18.3239 16.9482 20.6131 16 23 16C25.387 16 27.6761 16.9482 29.364 18.6361C31.0518 20.3239 32 22.6131 32 25ZM27.47 24.128L21.482 20.828C21.3298 20.7443 21.1583 20.7016 20.9846 20.7043C20.8108 20.707 20.6408 20.7549 20.4912 20.8433C20.3416 20.9317 20.2176 21.0576 20.1315 21.2086C20.0453 21.3595 20 21.5302 20 21.704V28.304C20 28.4778 20.0453 28.6486 20.1315 28.7995C20.2176 28.9504 20.3416 29.0763 20.4912 29.1647C20.6408 29.2531 20.8108 29.301 20.9846 29.3037C21.1583 29.3064 21.3298 29.2638 21.482 29.18L27.47 25.88C27.6268 25.7937 27.7575 25.6669 27.8486 25.5128C27.9397 25.3587 27.9877 25.183 27.9877 25.004C27.9877 24.825 27.9397 24.6493 27.8486 24.4952C27.7575 24.3412 27.6268 24.2143 27.47 24.128Z"
|
d="M23.404 0.452014C23.7033 0.35857 24.0204 0.336816 24.3297 0.388509C24.639 0.440203 24.9318 0.563895 25.1845 0.749599C25.4371 0.935304 25.6426 1.17782 25.7843 1.45756C25.9259 1.73731 25.9998 2.04644 26 2.36001V14.414C25.3462 14.2296 24.6766 14.1064 24 14.046V8.36001L10 12.736V27C10 28.1264 9.6197 29.2197 8.92071 30.1029C8.22172 30.9861 7.24499 31.6075 6.14877 31.8663C5.05255 32.125 3.90107 32.0061 2.88089 31.5287C1.86071 31.0514 1.03159 30.2435 0.52787 29.2361C0.024152 28.2286 -0.124656 27.0806 0.105556 25.9781C0.335768 24.8755 0.931513 23.883 1.79627 23.1613C2.66102 22.4396 3.74413 22.031 4.87009 22.0017C5.99606 21.9724 7.09893 22.3242 8.00001 23V6.73601C7.99982 6.30956 8.13596 5.8942 8.38854 5.55059C8.64112 5.20698 8.99692 4.9531 9.40401 4.82601L23.404 0.452014ZM10 10.64L24 6.26601V2.36001L10 6.73601V10.64ZM5.00001 24C4.20436 24 3.44129 24.3161 2.87869 24.8787C2.31608 25.4413 2.00001 26.2044 2.00001 27C2.00001 27.7957 2.31608 28.5587 2.87869 29.1213C3.44129 29.6839 4.20436 30 5.00001 30C5.79566 30 6.55872 29.6839 7.12133 29.1213C7.68394 28.5587 8.00001 27.7957 8.00001 27C8.00001 26.2044 7.68394 25.4413 7.12133 24.8787C6.55872 24.3161 5.79566 24 5.00001 24ZM32 25C32 27.387 31.0518 29.6761 29.364 31.364C27.6761 33.0518 25.387 34 23 34C20.6131 34 18.3239 33.0518 16.636 31.364C14.9482 29.6761 14 27.387 14 25C14 22.6131 14.9482 20.3239 16.636 18.6361C18.3239 16.9482 20.6131 16 23 16C25.387 16 27.6761 16.9482 29.364 18.6361C31.0518 20.3239 32 22.6131 32 25ZM27.47 24.128L21.482 20.828C21.3298 20.7443 21.1583 20.7016 20.9846 20.7043C20.8108 20.707 20.6408 20.7549 20.4912 20.8433C20.3416 20.9317 20.2176 21.0576 20.1315 21.2086C20.0453 21.3595 20 21.5302 20 21.704V28.304C20 28.4778 20.0453 28.6486 20.1315 28.7995C20.2176 28.9504 20.3416 29.0763 20.4912 29.1647C20.6408 29.2531 20.8108 29.301 20.9846 29.3037C21.1583 29.3064 21.3298 29.2638 21.482 29.18L27.47 25.88C27.6268 25.7937 27.7575 25.6669 27.8486 25.5128C27.9397 25.3587 27.9877 25.183 27.9877 25.004C27.9877 24.825 27.9397 24.6493 27.8486 24.4952C27.7575 24.3412 27.6268 24.2143 27.47 24.128Z"
|
||||||
fill="white"
|
fill="white"
|
||||||
|
|
@ -516,29 +652,57 @@ const FilterPage = () => {
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex flex-col lg:flex-row lg:gap-2">
|
<div className="flex flex-col lg:flex-row lg:gap-2">
|
||||||
<div className="text-gray-500 dark:text-gray-400 flex flex-row text-sm items-center">
|
<div className="text-gray-500 dark:text-gray-400 flex flex-row text-sm items-center">
|
||||||
{formatDateToIndonesian(new Date(audio?.createdAt))} {audio?.timezone ? audio?.timezone : "WIB"}
|
{formatDateToIndonesian(
|
||||||
|
new Date(audio?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{audio?.timezone ? audio?.timezone : "WIB"}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-500 dark:text-gray-400 flex flex-row text-sm items-center">
|
<div className="text-gray-500 dark:text-gray-400 flex flex-row text-sm items-center">
|
||||||
|
|
|
|
||||||
<Icon icon="formkit:eye" width="15" height="15" />
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>
|
||||||
{audio?.clickCount}{" "}
|
{audio?.clickCount}{" "}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">{audio?.title}</div>
|
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">
|
||||||
|
{audio?.title}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row items-center place-content-end gap-3">
|
<div className="flex flex-col lg:flex-row items-center place-content-end gap-3">
|
||||||
<img src="/assets/wave.svg" alt="wave" className="h-5 lg:h-16" />
|
<img
|
||||||
<svg width="17" height="20" viewBox="0 0 32 34" fill="null" xmlns="http://www.w3.org/2000/svg">
|
src="/assets/wave.svg"
|
||||||
|
alt="wave"
|
||||||
|
className="h-5 lg:h-16"
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
width="17"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 32 34"
|
||||||
|
fill="null"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M23.404 0.452014C23.7033 0.35857 24.0204 0.336816 24.3297 0.388509C24.639 0.440203 24.9318 0.563895 25.1845 0.749599C25.4371 0.935304 25.6426 1.17782 25.7843 1.45756C25.9259 1.73731 25.9998 2.04644 26 2.36001V14.414C25.3462 14.2296 24.6766 14.1064 24 14.046V8.36001L10 12.736V27C10 28.1264 9.6197 29.2197 8.92071 30.1029C8.22172 30.9861 7.24499 31.6075 6.14877 31.8663C5.05255 32.125 3.90107 32.0061 2.88089 31.5287C1.86071 31.0514 1.03159 30.2435 0.52787 29.2361C0.024152 28.2286 -0.124656 27.0806 0.105556 25.9781C0.335768 24.8755 0.931513 23.883 1.79627 23.1613C2.66102 22.4396 3.74413 22.031 4.87009 22.0017C5.99606 21.9724 7.09893 22.3242 8.00001 23V6.73601C7.99982 6.30956 8.13596 5.8942 8.38854 5.55059C8.64112 5.20698 8.99692 4.9531 9.40401 4.82601L23.404 0.452014ZM10 10.64L24 6.26601V2.36001L10 6.73601V10.64ZM5.00001 24C4.20436 24 3.44129 24.3161 2.87869 24.8787C2.31608 25.4413 2.00001 26.2044 2.00001 27C2.00001 27.7957 2.31608 28.5587 2.87869 29.1213C3.44129 29.6839 4.20436 30 5.00001 30C5.79566 30 6.55872 29.6839 7.12133 29.1213C7.68394 28.5587 8.00001 27.7957 8.00001 27C8.00001 26.2044 7.68394 25.4413 7.12133 24.8787C6.55872 24.3161 5.79566 24 5.00001 24ZM32 25C32 27.387 31.0518 29.6761 29.364 31.364C27.6761 33.0518 25.387 34 23 34C20.6131 34 18.3239 33.0518 16.636 31.364C14.9482 29.6761 14 27.387 14 25C14 22.6131 14.9482 20.3239 16.636 18.6361C18.3239 16.9482 20.6131 16 23 16C25.387 16 27.6761 16.9482 29.364 18.6361C31.0518 20.3239 32 22.6131 32 25ZM27.47 24.128L21.482 20.828C21.3298 20.7443 21.1583 20.7016 20.9846 20.7043C20.8108 20.707 20.6408 20.7549 20.4912 20.8433C20.3416 20.9317 20.2176 21.0576 20.1315 21.2086C20.0453 21.3595 20 21.5302 20 21.704V28.304C20 28.4778 20.0453 28.6486 20.1315 28.7995C20.2176 28.9504 20.3416 29.0763 20.4912 29.1647C20.6408 29.2531 20.8108 29.301 20.9846 29.3037C21.1583 29.3064 21.3298 29.2638 21.482 29.18L27.47 25.88C27.6268 25.7937 27.7575 25.6669 27.8486 25.5128C27.9397 25.3587 27.9877 25.183 27.9877 25.004C27.9877 24.825 27.9397 24.6493 27.8486 24.4952C27.7575 24.3412 27.6268 24.2143 27.47 24.128Z"
|
d="M23.404 0.452014C23.7033 0.35857 24.0204 0.336816 24.3297 0.388509C24.639 0.440203 24.9318 0.563895 25.1845 0.749599C25.4371 0.935304 25.6426 1.17782 25.7843 1.45756C25.9259 1.73731 25.9998 2.04644 26 2.36001V14.414C25.3462 14.2296 24.6766 14.1064 24 14.046V8.36001L10 12.736V27C10 28.1264 9.6197 29.2197 8.92071 30.1029C8.22172 30.9861 7.24499 31.6075 6.14877 31.8663C5.05255 32.125 3.90107 32.0061 2.88089 31.5287C1.86071 31.0514 1.03159 30.2435 0.52787 29.2361C0.024152 28.2286 -0.124656 27.0806 0.105556 25.9781C0.335768 24.8755 0.931513 23.883 1.79627 23.1613C2.66102 22.4396 3.74413 22.031 4.87009 22.0017C5.99606 21.9724 7.09893 22.3242 8.00001 23V6.73601C7.99982 6.30956 8.13596 5.8942 8.38854 5.55059C8.64112 5.20698 8.99692 4.9531 9.40401 4.82601L23.404 0.452014ZM10 10.64L24 6.26601V2.36001L10 6.73601V10.64ZM5.00001 24C4.20436 24 3.44129 24.3161 2.87869 24.8787C2.31608 25.4413 2.00001 26.2044 2.00001 27C2.00001 27.7957 2.31608 28.5587 2.87869 29.1213C3.44129 29.6839 4.20436 30 5.00001 30C5.79566 30 6.55872 29.6839 7.12133 29.1213C7.68394 28.5587 8.00001 27.7957 8.00001 27C8.00001 26.2044 7.68394 25.4413 7.12133 24.8787C6.55872 24.3161 5.79566 24 5.00001 24ZM32 25C32 27.387 31.0518 29.6761 29.364 31.364C27.6761 33.0518 25.387 34 23 34C20.6131 34 18.3239 33.0518 16.636 31.364C14.9482 29.6761 14 27.387 14 25C14 22.6131 14.9482 20.3239 16.636 18.6361C18.3239 16.9482 20.6131 16 23 16C25.387 16 27.6761 16.9482 29.364 18.6361C31.0518 20.3239 32 22.6131 32 25ZM27.47 24.128L21.482 20.828C21.3298 20.7443 21.1583 20.7016 20.9846 20.7043C20.8108 20.707 20.6408 20.7549 20.4912 20.8433C20.3416 20.9317 20.2176 21.0576 20.1315 21.2086C20.0453 21.3595 20 21.5302 20 21.704V28.304C20 28.4778 20.0453 28.6486 20.1315 28.7995C20.2176 28.9504 20.3416 29.0763 20.4912 29.1647C20.6408 29.2531 20.8108 29.301 20.9846 29.3037C21.1583 29.3064 21.3298 29.2638 21.482 29.18L27.47 25.88C27.6268 25.7937 27.7575 25.6669 27.8486 25.5128C27.9397 25.3587 27.9877 25.183 27.9877 25.004C27.9877 24.825 27.9397 24.6493 27.8486 24.4952C27.7575 24.3412 27.6268 24.2143 27.47 24.128Z"
|
||||||
fill="black"
|
fill="black"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<p className="text-xs lg:text-sm text-center"> {audio?.duration ? secondToTimes(Number(audio?.duration)) : "00:00:00"}</p>
|
<p className="text-xs lg:text-sm text-center">
|
||||||
<Icon icon="ph:download-fill" className="text-red-500" fontSize={20} />
|
{" "}
|
||||||
|
{audio?.duration
|
||||||
|
? secondToTimes(Number(audio?.duration))
|
||||||
|
: "00:00:00"}
|
||||||
|
</p>
|
||||||
|
<Icon
|
||||||
|
icon="ph:download-fill"
|
||||||
|
className="text-red-500"
|
||||||
|
fontSize={20}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -547,13 +711,21 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center text-black">
|
<p className="flex items-center justify-center text-black">
|
||||||
<img src="/assets/empty-data.png" alt="empty" className="h-60 w-60 my-4" />
|
<img
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
className="h-60 w-60 my-4"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<LandingPagination table={table} totalData={totalData} totalPage={totalPage} />
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,7 @@ const Galery = (props: any) => {
|
||||||
className="flex cursor-pointer"
|
className="flex cursor-pointer"
|
||||||
asChild
|
asChild
|
||||||
>
|
>
|
||||||
<a className="flex justify-end items-end place-items-end">
|
<a className="flex justify-end items-center">
|
||||||
<Icon
|
<Icon
|
||||||
className="text-white ml-1"
|
className="text-white ml-1"
|
||||||
fontSize={25}
|
fontSize={25}
|
||||||
|
|
@ -444,10 +444,34 @@ const Galery = (props: any) => {
|
||||||
</a>
|
</a>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-52">
|
<PopoverContent className="w-52">
|
||||||
{/* <Link href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
|
<div
|
||||||
<Icon icon="jam:write" fontSize={25} />
|
onClick={() =>
|
||||||
<p className="text-base font-semibold mb-2">Content Rewrite</p>
|
handleSaveWishlist(
|
||||||
</Link> */}
|
video?.mediaUpload?.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="cursor-pointer flex flex-row gap-2 hover:text-red-800"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="material-symbols:bookmark-outline"
|
||||||
|
fontSize={25}
|
||||||
|
/>
|
||||||
|
<p className="text-base font-semibold mb-2">
|
||||||
|
{t("save")}{" "}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`}
|
||||||
|
className="flex flex-row hover:text-red-800 gap-2"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="jam:write"
|
||||||
|
fontSize={25}
|
||||||
|
/>
|
||||||
|
<p className="text-base font-semibold mb-2">
|
||||||
|
Content Rewrite
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
|
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
|
|
@ -457,14 +481,14 @@ const Galery = (props: any) => {
|
||||||
fontSize={20}
|
fontSize={20}
|
||||||
/>
|
/>
|
||||||
<p className="text-base font-semibold mb-1">
|
<p className="text-base font-semibold mb-1">
|
||||||
{t("share")}
|
{t("share")}{" "}
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="mb-2">
|
<h1 className="mb-2">
|
||||||
{t("shareTo")}
|
{t("shareTo")}{" "}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex flex-col mb-2">
|
<div className="flex flex-col mb-2">
|
||||||
<p className="text-base font-semibold mb-1">
|
<p className="text-base font-semibold mb-1">
|
||||||
|
|
@ -479,9 +503,7 @@ const Galery = (props: any) => {
|
||||||
}
|
}
|
||||||
onKeyPress={handleEmailList}
|
onKeyPress={handleEmailList}
|
||||||
type="email"
|
type="email"
|
||||||
placeholder={t(
|
placeholder={t("shareTo")}
|
||||||
"pressEnter"
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -494,20 +516,6 @@ const Galery = (props: any) => {
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
onClick={() =>
|
|
||||||
handleDelete(video?.id)
|
|
||||||
}
|
|
||||||
className="cursor-pointer flex flex-row gap-2 hover:text-red-800"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon="iconamoon:trash"
|
|
||||||
fontSize={25}
|
|
||||||
/>
|
|
||||||
<p className="text-base font-semibold mb-2">
|
|
||||||
{t("delete")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -702,7 +710,7 @@ const Galery = (props: any) => {
|
||||||
className="flex cursor-pointer"
|
className="flex cursor-pointer"
|
||||||
asChild
|
asChild
|
||||||
>
|
>
|
||||||
<a className="flex justify-end items-end place-items-end">
|
<a className="flex justify-end items-center">
|
||||||
<Icon
|
<Icon
|
||||||
className="text-white ml-1"
|
className="text-white ml-1"
|
||||||
fontSize={25}
|
fontSize={25}
|
||||||
|
|
@ -711,10 +719,34 @@ const Galery = (props: any) => {
|
||||||
</a>
|
</a>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-52">
|
<PopoverContent className="w-52">
|
||||||
{/* <Link href={`/content-management/rewrite/create/${video?.mediaUpload?.id}`} className="flex flex-row hover:text-red-800 gap-2">
|
<div
|
||||||
<Icon icon="jam:write" fontSize={25} />
|
onClick={() =>
|
||||||
<p className="text-base font-semibold mb-2">Content Rewrite</p>
|
handleSaveWishlist(
|
||||||
</Link> */}
|
image?.mediaUpload?.id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="cursor-pointer flex flex-row gap-2 hover:text-red-800"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="material-symbols:bookmark-outline"
|
||||||
|
fontSize={25}
|
||||||
|
/>
|
||||||
|
<p className="text-base font-semibold mb-2">
|
||||||
|
{t("save")}{" "}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href={`/content-management/rewrite/create/${image?.mediaUpload?.id}`}
|
||||||
|
className="flex flex-row hover:text-red-800 gap-2"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
icon="jam:write"
|
||||||
|
fontSize={25}
|
||||||
|
/>
|
||||||
|
<p className="text-base font-semibold mb-2">
|
||||||
|
Content Rewrite
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
|
<div className="flex items-center gap-1 hover:text-red-800 w-full rounded-lg">
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
|
|
@ -724,14 +756,14 @@ const Galery = (props: any) => {
|
||||||
fontSize={20}
|
fontSize={20}
|
||||||
/>
|
/>
|
||||||
<p className="text-base font-semibold mb-1">
|
<p className="text-base font-semibold mb-1">
|
||||||
{t("share")}
|
{t("share")}{" "}
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<h1 className="mb-2">
|
<h1 className="mb-2">
|
||||||
{t("shareTo")}
|
{t("shareTo")}{" "}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex flex-col mb-2">
|
<div className="flex flex-col mb-2">
|
||||||
<p className="text-base font-semibold mb-1">
|
<p className="text-base font-semibold mb-1">
|
||||||
|
|
@ -746,9 +778,7 @@ const Galery = (props: any) => {
|
||||||
}
|
}
|
||||||
onKeyPress={handleEmailList}
|
onKeyPress={handleEmailList}
|
||||||
type="email"
|
type="email"
|
||||||
placeholder={t(
|
placeholder={t("shareTo")}
|
||||||
"pressEnter"
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -761,20 +791,6 @@ const Galery = (props: any) => {
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
onClick={() =>
|
|
||||||
handleDelete(image?.id)
|
|
||||||
}
|
|
||||||
className="cursor-pointer flex flex-row gap-2 hover:text-red-800"
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
icon="iconamoon:trash"
|
|
||||||
fontSize={25}
|
|
||||||
/>
|
|
||||||
<p className="text-base font-semibold mb-2">
|
|
||||||
{t("delete")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,12 @@ const page = (props: any) => {
|
||||||
const [selectedArticleId, setSelectedArticleId] = useState<any>(null);
|
const [selectedArticleId, setSelectedArticleId] = useState<any>(null);
|
||||||
const [articleBody, setArticleBody] = useState("");
|
const [articleBody, setArticleBody] = useState("");
|
||||||
const [selectedAdvConfig, setSelectedAdvConfig] = useState("");
|
const [selectedAdvConfig, setSelectedAdvConfig] = useState("");
|
||||||
const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||||
const [selectedContextType, setSelectedContextType] = useState("");
|
useState("profesional");
|
||||||
const [selectedLanguage, setSelectedLanguage] = useState("");
|
const [selectedContextType, setSelectedContextType] = useState("article");
|
||||||
|
const [selectedLanguage, setSelectedLanguage] = useState("id");
|
||||||
const [selectedTitle, setSelectedTitle] = useState("");
|
const [selectedTitle, setSelectedTitle] = useState("");
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("news");
|
||||||
const [detailArticle, setDetailArticle] = useState<any>(null);
|
const [detailArticle, setDetailArticle] = useState<any>(null);
|
||||||
const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
|
const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
|
|
@ -262,11 +263,11 @@ const page = (props: any) => {
|
||||||
setIsGeneratedArticle(true);
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
setArticleIds((prevIds: any) => {
|
setArticleIds((prevIds: any) => {
|
||||||
if (prevIds.length < 5) {
|
if (prevIds.length < 3) {
|
||||||
return [...prevIds, newArticleId];
|
return [...prevIds, newArticleId];
|
||||||
} else {
|
} else {
|
||||||
const updatedIds = [...prevIds];
|
const updatedIds = [...prevIds];
|
||||||
updatedIds[4] = newArticleId;
|
updatedIds[2] = newArticleId;
|
||||||
return updatedIds;
|
return updatedIds;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -488,11 +489,11 @@ const page = (props: any) => {
|
||||||
Generate Artikel
|
Generate Artikel
|
||||||
</a>
|
</a>
|
||||||
{isGeneratedArticle && (
|
{isGeneratedArticle && (
|
||||||
<div className="mt-3 ml-2 pb-0">
|
<div className="mt-3 pb-0 flex flex-row gap-3">
|
||||||
{articleIds.map((id: any, index: any) => (
|
{articleIds.map((id: any, index: any) => (
|
||||||
<p
|
<p
|
||||||
key={index}
|
key={index}
|
||||||
className={` w-fit rounded-md p-3 m-1 ${
|
className={` w-fit rounded-md p-3 mt-2 ${
|
||||||
Number(selectedArticleId) === Number(id)
|
Number(selectedArticleId) === Number(id)
|
||||||
? "text-white w-fit p-3 hover:text-white cursor-pointer bg-[#31ce36] border-[#31ce36]"
|
? "text-white w-fit p-3 hover:text-white cursor-pointer bg-[#31ce36] border-[#31ce36]"
|
||||||
: "text-[#48abf7] p-3 hover:text-white hover:bg-[#48abf7] w-fit cursor-pointer border border-[#48abf7]"
|
: "text-[#48abf7] p-3 hover:text-white hover:bg-[#48abf7] w-fit cursor-pointer border border-[#48abf7]"
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ const page = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="font-semibold mb-3 text-black gap-2">
|
<div className="font-light mb-3 text-black gap-2">
|
||||||
<label htmlFor="description" className="text-black dark:text-white">
|
<label htmlFor="description" className="text-black dark:text-white">
|
||||||
Deskripsi Artikel
|
Deskripsi Artikel
|
||||||
</label>
|
</label>
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,31 @@ import React, { useEffect, useState } from "react";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { formatDateToIndonesian, getOnlyDate, getOnlyMonthAndYear } from "@/utils/globals";
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { getListContent, getUserLevelListByParent, listCategory, listData, listDataRegional } from "@/service/landing/landing";
|
import {
|
||||||
import { ColumnDef, ColumnFiltersState, PaginationState, SortingState, VisibilityState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
getListContent,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listCategory,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
import LandingPagination from "@/components/landing-page/pagination";
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
|
@ -35,8 +56,11 @@ const FilterPage = () => {
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
[]
|
||||||
|
);
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
|
|
@ -57,7 +81,9 @@ const FilterPage = () => {
|
||||||
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
||||||
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
const [searchTitle, setSearchTitle] = useState<string>("");
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
const [sortByOpt, setSortByOpt] = useState<any>(sortBy === "popular" ? "clickCount" : "createdAt");
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
const isRegional = asPath?.includes("regional");
|
const isRegional = asPath?.includes("regional");
|
||||||
const isSatker = asPath?.includes("satker");
|
const isSatker = asPath?.includes("satker");
|
||||||
const [formatFilter, setFormatFilter] = useState<any>([]);
|
const [formatFilter, setFormatFilter] = useState<any>([]);
|
||||||
|
|
@ -102,8 +128,14 @@ const FilterPage = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (categorie) {
|
if (categorie) {
|
||||||
setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
setCategoryFilter(
|
||||||
console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Kategori",
|
||||||
|
categorie,
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [categorie]);
|
}, [categorie]);
|
||||||
|
|
||||||
|
|
@ -121,7 +153,19 @@ const FilterPage = () => {
|
||||||
}
|
}
|
||||||
console.log(monthYearFilter, "monthFilter");
|
console.log(monthYearFilter, "monthFilter");
|
||||||
initState();
|
initState();
|
||||||
}, [change, asPath, monthYearFilter, page, sortBy, sortByOpt, title, startDateString, endDateString, categorie, formatFilter]);
|
}, [
|
||||||
|
change,
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
async function getCategories() {
|
async function getCategories() {
|
||||||
const category = await listCategory("3");
|
const category = await listCategory("3");
|
||||||
|
|
@ -144,7 +188,10 @@ const FilterPage = () => {
|
||||||
async function getDataAll() {
|
async function getDataAll() {
|
||||||
if (asPath?.includes("/polda/") == true) {
|
if (asPath?.includes("/polda/") == true) {
|
||||||
if (asPath?.split("/")[2] !== "[polda_name]") {
|
if (asPath?.split("/")[2] !== "[polda_name]") {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -162,8 +209,14 @@ const FilterPage = () => {
|
||||||
filterGroup,
|
filterGroup,
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)
|
||||||
|
?.split("/")[0]
|
||||||
|
?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -178,7 +231,10 @@ const FilterPage = () => {
|
||||||
setTotalContent(response?.data?.data?.totalElements);
|
setTotalContent(response?.data?.data?.totalElements);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -195,8 +251,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -247,7 +307,10 @@ const FilterPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDataRegional() {
|
async function getDataRegional() {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -260,8 +323,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
12,
|
12,
|
||||||
pages,
|
pages,
|
||||||
sortByOpt
|
sortByOpt
|
||||||
|
|
@ -394,7 +461,7 @@ const FilterPage = () => {
|
||||||
|
|
||||||
{/* Left */}
|
{/* Left */}
|
||||||
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
||||||
<div className="lg:w-[25%] w-full bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
Filter
|
Filter
|
||||||
|
|
@ -402,7 +469,10 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="search" className="block text-sm font-medium text-gray-700 dark:text-white">
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
{t("search")}
|
{t("search")}
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -418,7 +488,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("monthYear")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear")}
|
||||||
|
</label>
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selected={monthYearFilter}
|
selected={monthYearFilter}
|
||||||
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
|
@ -430,7 +502,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("date")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date")}
|
||||||
|
</label>
|
||||||
<div className="flex flex-row justify justify-between gap-2">
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selectsRange
|
selectsRange
|
||||||
|
|
@ -443,18 +517,44 @@ const FilterPage = () => {
|
||||||
placeholderText={t("selectDate")}
|
placeholderText={t("selectDate")}
|
||||||
onCalendarClose={() => setCalenderState(!calenderState)}
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center">{handleClose ? <Icon icon="carbon:close-filled" onClick={handleDeleteDate} width="20" inline color="#216ba5" /> : ""}</div>
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">{t("categories")}</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories")}
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
{categories.map((category: any) => (
|
{categories.map((category: any) => (
|
||||||
<li key={category?.id}>
|
<li key={category?.id}>
|
||||||
<label className="inline-flex items-center" htmlFor={`${category.id}`}>
|
<label
|
||||||
<Checkbox id={`${category.id}`} value={category.id} checked={categoryFilter.includes(String(category.id))} onCheckedChange={(e) => handleCategoryFilter(Boolean(e), category.id)} />
|
className="inline-flex items-center"
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">{category?.name}</span>
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -464,43 +564,93 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
{/* Garis */}
|
{/* Garis */}
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">Format</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="doc" value="doc" checked={formatFilter.includes("doc")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "doc")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">DOC</span>
|
id="doc"
|
||||||
|
value="doc"
|
||||||
|
checked={formatFilter.includes("doc")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "doc")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
DOC
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="docx" value="docx" checked={formatFilter.includes("docx")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "docx")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">DOCX</span>
|
id="docx"
|
||||||
|
value="docx"
|
||||||
|
checked={formatFilter.includes("docx")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "docx")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
DOCX
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="pdf" value="pdf" checked={formatFilter.includes("pdf")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "pdf")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">PDF</span>
|
id="pdf"
|
||||||
|
value="pdf"
|
||||||
|
checked={formatFilter.includes("pdf")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "pdf")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PDF
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="ppt" value="ppt" checked={formatFilter.includes("ppt")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "ppt")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">PPT</span>
|
id="ppt"
|
||||||
|
value="ppt"
|
||||||
|
checked={formatFilter.includes("ppt")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "ppt")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PPT
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="pptx" value="pptx" checked={formatFilter.includes("pptx")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "pptx")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">PPTX</span>
|
id="pptx"
|
||||||
|
value="pptx"
|
||||||
|
checked={formatFilter.includes("pptx")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "pptx")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PPTX
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-black dark:border-white my-4"></div>
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<a onClick={cleanCheckbox} className="text-[#bb3523] cursor-pointer">
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
<b>Reset Filter</b>
|
<b>Reset Filter</b>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -513,7 +663,11 @@ const FilterPage = () => {
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex flex-col items-end mb-4">
|
<div className="flex flex-col items-end mb-4">
|
||||||
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
||||||
<select defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} onChange={(e) => handleSorting(e)} className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500">
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
|
||||||
|
onChange={(e) => handleSorting(e)}
|
||||||
|
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
>
|
||||||
<option value="latest">{t("latest")}</option>
|
<option value="latest">{t("latest")}</option>
|
||||||
<option value="popular">{t("mostPopular")}</option>
|
<option value="popular">{t("mostPopular")}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -539,9 +693,19 @@ const FilterPage = () => {
|
||||||
{documentData?.length > 0 ? (
|
{documentData?.length > 0 ? (
|
||||||
<div className=" grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className=" grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{documentData?.map((document: any) => (
|
{documentData?.map((document: any) => (
|
||||||
<Link href={`/document/detail/${document?.slug}`} key={document?.id} className="flex flex-col bg-yellow-500 sm:flex-row items-center dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full">
|
<Link
|
||||||
|
href={`/document/detail/${document?.slug}`}
|
||||||
|
key={document?.id}
|
||||||
|
className="flex flex-col bg-yellow-500 sm:flex-row items-center dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4 w-full"
|
||||||
|
>
|
||||||
<div className="flex items-center justify-center rounded-lg w-16 h-16">
|
<div className="flex items-center justify-center rounded-lg w-16 h-16">
|
||||||
<svg width="28" height="34" viewBox="0 0 28 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg
|
||||||
|
width="28"
|
||||||
|
height="34"
|
||||||
|
viewBox="0 0 28 34"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M5.6665 17.4167C5.6665 17.0851 5.7982 16.7672 6.03262 16.5328C6.26704 16.2984 6.58498 16.1667 6.9165 16.1667C7.24802 16.1667 7.56597 16.2984 7.80039 16.5328C8.03481 16.7672 8.1665 17.0851 8.1665 17.4167C8.1665 17.7482 8.03481 18.0661 7.80039 18.3005C7.56597 18.535 7.24802 18.6667 6.9165 18.6667C6.58498 18.6667 6.26704 18.535 6.03262 18.3005C5.7982 18.0661 5.6665 17.7482 5.6665 17.4167ZM6.9165 21.1667C6.58498 21.1667 6.26704 21.2984 6.03262 21.5328C5.7982 21.7672 5.6665 22.0851 5.6665 22.4167C5.6665 22.7482 5.7982 23.0661 6.03262 23.3005C6.26704 23.535 6.58498 23.6667 6.9165 23.6667C7.24802 23.6667 7.56597 23.535 7.80039 23.3005C8.03481 23.0661 8.1665 22.7482 8.1665 22.4167C8.1665 22.0851 8.03481 21.7672 7.80039 21.5328C7.56597 21.2984 7.24802 21.1667 6.9165 21.1667ZM5.6665 27.4167C5.6665 27.0851 5.7982 26.7672 6.03262 26.5328C6.26704 26.2984 6.58498 26.1667 6.9165 26.1667C7.24802 26.1667 7.56597 26.2984 7.80039 26.5328C8.03481 26.7672 8.1665 27.0851 8.1665 27.4167C8.1665 27.7482 8.03481 28.0661 7.80039 28.3005C7.56597 28.535 7.24802 28.6667 6.9165 28.6667C6.58498 28.6667 6.26704 28.535 6.03262 28.3005C5.7982 28.0661 5.6665 27.7482 5.6665 27.4167ZM11.9165 16.1667C11.585 16.1667 11.267 16.2984 11.0326 16.5328C10.7982 16.7672 10.6665 17.0851 10.6665 17.4167C10.6665 17.7482 10.7982 18.0661 11.0326 18.3005C11.267 18.535 11.585 18.6667 11.9165 18.6667H21.0832C21.4147 18.6667 21.7326 18.535 21.9671 18.3005C22.2015 18.0661 22.3332 17.7482 22.3332 17.4167C22.3332 17.0851 22.2015 16.7672 21.9671 16.5328C21.7326 16.2984 21.4147 16.1667 21.0832 16.1667H11.9165ZM10.6665 22.4167C10.6665 22.0851 10.7982 21.7672 11.0326 21.5328C11.267 21.2984 11.585 21.1667 11.9165 21.1667H21.0832C21.4147 21.1667 21.7326 21.2984 21.9671 21.5328C22.2015 21.7672 22.3332 22.0851 22.3332 22.4167C22.3332 22.7482 22.2015 23.0661 21.9671 23.3005C21.7326 23.535 21.4147 23.6667 21.0832 23.6667H11.9165C11.585 23.6667 11.267 23.535 11.0326 23.3005C10.7982 23.0661 10.6665 22.7482 10.6665 22.4167ZM11.9165 26.1667C11.585 26.1667 11.267 26.2984 11.0326 26.5328C10.7982 26.7672 10.6665 27.0851 10.6665 27.4167C10.6665 27.7482 10.7982 28.0661 11.0326 28.3005C11.267 28.535 11.585 28.6667 11.9165 28.6667H21.0832C21.4147 28.6667 21.7326 28.535 21.9671 28.3005C22.2015 28.0661 22.3332 27.7482 22.3332 27.4167C22.3332 27.0851 22.2015 26.7672 21.9671 26.5328C21.7326 26.2984 21.4147 26.1667 21.0832 26.1667H11.9165ZM26.3565 11.0233L16.6415 1.31C16.6157 1.28605 16.5885 1.26378 16.5598 1.24333C16.5392 1.22742 16.5192 1.21074 16.4998 1.19333C16.3852 1.08512 16.2632 0.984882 16.1348 0.893332C16.0922 0.865802 16.0476 0.841298 16.0015 0.819999L15.9215 0.779999L15.8382 0.731666C15.7482 0.679999 15.6565 0.626665 15.5615 0.586665C15.2296 0.454104 14.8783 0.376423 14.5215 0.356665C14.4885 0.354519 14.4557 0.350625 14.4232 0.344999C14.3779 0.338012 14.3323 0.334114 14.2865 0.333332H3.99984C3.11578 0.333332 2.26794 0.684521 1.64281 1.30964C1.01769 1.93476 0.666504 2.78261 0.666504 3.66667V30.3333C0.666504 31.2174 1.01769 32.0652 1.64281 32.6904C2.26794 33.3155 3.11578 33.6667 3.99984 33.6667H23.9998C24.8839 33.6667 25.7317 33.3155 26.3569 32.6904C26.982 32.0652 27.3332 31.2174 27.3332 30.3333V13.38C27.333 12.496 26.9817 11.6483 26.3565 11.0233ZM24.8332 30.3333C24.8332 30.5543 24.7454 30.7663 24.5891 30.9226C24.4328 31.0789 24.2208 31.1667 23.9998 31.1667H3.99984C3.77882 31.1667 3.56686 31.0789 3.41058 30.9226C3.2543 30.7663 3.1665 30.5543 3.1665 30.3333V3.66667C3.1665 3.44565 3.2543 3.23369 3.41058 3.07741C3.56686 2.92113 3.77882 2.83333 3.99984 2.83333H13.9998V10.3333C13.9998 11.2174 14.351 12.0652 14.9761 12.6904C15.6013 13.3155 16.4491 13.6667 17.3332 13.6667H24.8332V30.3333ZM16.4998 4.70166L22.9632 11.1667H17.3332C17.1122 11.1667 16.9002 11.0789 16.7439 10.9226C16.5876 10.7663 16.4998 10.5543 16.4998 10.3333V4.70166Z"
|
d="M5.6665 17.4167C5.6665 17.0851 5.7982 16.7672 6.03262 16.5328C6.26704 16.2984 6.58498 16.1667 6.9165 16.1667C7.24802 16.1667 7.56597 16.2984 7.80039 16.5328C8.03481 16.7672 8.1665 17.0851 8.1665 17.4167C8.1665 17.7482 8.03481 18.0661 7.80039 18.3005C7.56597 18.535 7.24802 18.6667 6.9165 18.6667C6.58498 18.6667 6.26704 18.535 6.03262 18.3005C5.7982 18.0661 5.6665 17.7482 5.6665 17.4167ZM6.9165 21.1667C6.58498 21.1667 6.26704 21.2984 6.03262 21.5328C5.7982 21.7672 5.6665 22.0851 5.6665 22.4167C5.6665 22.7482 5.7982 23.0661 6.03262 23.3005C6.26704 23.535 6.58498 23.6667 6.9165 23.6667C7.24802 23.6667 7.56597 23.535 7.80039 23.3005C8.03481 23.0661 8.1665 22.7482 8.1665 22.4167C8.1665 22.0851 8.03481 21.7672 7.80039 21.5328C7.56597 21.2984 7.24802 21.1667 6.9165 21.1667ZM5.6665 27.4167C5.6665 27.0851 5.7982 26.7672 6.03262 26.5328C6.26704 26.2984 6.58498 26.1667 6.9165 26.1667C7.24802 26.1667 7.56597 26.2984 7.80039 26.5328C8.03481 26.7672 8.1665 27.0851 8.1665 27.4167C8.1665 27.7482 8.03481 28.0661 7.80039 28.3005C7.56597 28.535 7.24802 28.6667 6.9165 28.6667C6.58498 28.6667 6.26704 28.535 6.03262 28.3005C5.7982 28.0661 5.6665 27.7482 5.6665 27.4167ZM11.9165 16.1667C11.585 16.1667 11.267 16.2984 11.0326 16.5328C10.7982 16.7672 10.6665 17.0851 10.6665 17.4167C10.6665 17.7482 10.7982 18.0661 11.0326 18.3005C11.267 18.535 11.585 18.6667 11.9165 18.6667H21.0832C21.4147 18.6667 21.7326 18.535 21.9671 18.3005C22.2015 18.0661 22.3332 17.7482 22.3332 17.4167C22.3332 17.0851 22.2015 16.7672 21.9671 16.5328C21.7326 16.2984 21.4147 16.1667 21.0832 16.1667H11.9165ZM10.6665 22.4167C10.6665 22.0851 10.7982 21.7672 11.0326 21.5328C11.267 21.2984 11.585 21.1667 11.9165 21.1667H21.0832C21.4147 21.1667 21.7326 21.2984 21.9671 21.5328C22.2015 21.7672 22.3332 22.0851 22.3332 22.4167C22.3332 22.7482 22.2015 23.0661 21.9671 23.3005C21.7326 23.535 21.4147 23.6667 21.0832 23.6667H11.9165C11.585 23.6667 11.267 23.535 11.0326 23.3005C10.7982 23.0661 10.6665 22.7482 10.6665 22.4167ZM11.9165 26.1667C11.585 26.1667 11.267 26.2984 11.0326 26.5328C10.7982 26.7672 10.6665 27.0851 10.6665 27.4167C10.6665 27.7482 10.7982 28.0661 11.0326 28.3005C11.267 28.535 11.585 28.6667 11.9165 28.6667H21.0832C21.4147 28.6667 21.7326 28.535 21.9671 28.3005C22.2015 28.0661 22.3332 27.7482 22.3332 27.4167C22.3332 27.0851 22.2015 26.7672 21.9671 26.5328C21.7326 26.2984 21.4147 26.1667 21.0832 26.1667H11.9165ZM26.3565 11.0233L16.6415 1.31C16.6157 1.28605 16.5885 1.26378 16.5598 1.24333C16.5392 1.22742 16.5192 1.21074 16.4998 1.19333C16.3852 1.08512 16.2632 0.984882 16.1348 0.893332C16.0922 0.865802 16.0476 0.841298 16.0015 0.819999L15.9215 0.779999L15.8382 0.731666C15.7482 0.679999 15.6565 0.626665 15.5615 0.586665C15.2296 0.454104 14.8783 0.376423 14.5215 0.356665C14.4885 0.354519 14.4557 0.350625 14.4232 0.344999C14.3779 0.338012 14.3323 0.334114 14.2865 0.333332H3.99984C3.11578 0.333332 2.26794 0.684521 1.64281 1.30964C1.01769 1.93476 0.666504 2.78261 0.666504 3.66667V30.3333C0.666504 31.2174 1.01769 32.0652 1.64281 32.6904C2.26794 33.3155 3.11578 33.6667 3.99984 33.6667H23.9998C24.8839 33.6667 25.7317 33.3155 26.3569 32.6904C26.982 32.0652 27.3332 31.2174 27.3332 30.3333V13.38C27.333 12.496 26.9817 11.6483 26.3565 11.0233ZM24.8332 30.3333C24.8332 30.5543 24.7454 30.7663 24.5891 30.9226C24.4328 31.0789 24.2208 31.1667 23.9998 31.1667H3.99984C3.77882 31.1667 3.56686 31.0789 3.41058 30.9226C3.2543 30.7663 3.1665 30.5543 3.1665 30.3333V3.66667C3.1665 3.44565 3.2543 3.23369 3.41058 3.07741C3.56686 2.92113 3.77882 2.83333 3.99984 2.83333H13.9998V10.3333C13.9998 11.2174 14.351 12.0652 14.9761 12.6904C15.6013 13.3155 16.4491 13.6667 17.3332 13.6667H24.8332V30.3333ZM16.4998 4.70166L22.9632 11.1667H17.3332C17.1122 11.1667 16.9002 11.0789 16.7439 10.9226C16.5876 10.7663 16.4998 10.5543 16.4998 10.3333V4.70166Z"
|
||||||
fill="black"
|
fill="black"
|
||||||
|
|
@ -550,12 +714,28 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col flex-1 gap-2">
|
<div className="flex flex-col flex-1 gap-2">
|
||||||
<div className="text-gray-500 dark:text-gray-400 flex flex-row items-center gap-2 text-xs">
|
<div className="text-gray-500 dark:text-gray-400 flex flex-row items-center gap-2 text-xs">
|
||||||
{formatDateToIndonesian(new Date(document?.createdAt))} {document?.timezone ? document?.timezone : "WIB"} | <Icon icon="formkit:eye" width="15" height="15" /> {document?.clickCount}
|
{formatDateToIndonesian(
|
||||||
|
new Date(document?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{document?.timezone ? document?.timezone : "WIB"}{" "}
|
||||||
|
|{" "}
|
||||||
|
<Icon icon="formkit:eye" width="15" height="15" />{" "}
|
||||||
|
{document?.clickCount}
|
||||||
|
</div>
|
||||||
|
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm">
|
||||||
|
{document?.title}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm">{document?.title}</div>
|
|
||||||
<div className="flex gap-2 items-center text-xs text-red-500 dark:text-red-500">
|
<div className="flex gap-2 items-center text-xs text-red-500 dark:text-red-500">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512">
|
<svg
|
||||||
<path fill="#f00" d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z" />
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="#f00"
|
||||||
|
d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
Download Dokumen
|
Download Dokumen
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -565,13 +745,21 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center">
|
<p className="flex items-center justify-center">
|
||||||
<img src="/assets/empty-data.png" alt="empty" className="h-60 w-60 my-4" />
|
<img
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
className="h-60 w-60 my-4"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<LandingPagination table={table} totalData={totalData} totalPage={totalPage} />
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,30 @@ import React, { useEffect, useState } from "react";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { formatDateToIndonesian, getOnlyDate, getOnlyMonthAndYear } from "@/utils/globals";
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { getUserLevelListByParent, listCategory, listData, listDataRegional } from "@/service/landing/landing";
|
import {
|
||||||
import { ColumnDef, ColumnFiltersState, PaginationState, SortingState, VisibilityState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
getUserLevelListByParent,
|
||||||
|
listCategory,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
import LandingPagination from "@/components/landing-page/pagination";
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
|
@ -38,8 +58,11 @@ const FilterPage = () => {
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
[]
|
||||||
|
);
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
|
|
@ -60,7 +83,9 @@ const FilterPage = () => {
|
||||||
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
||||||
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
const [searchTitle, setSearchTitle] = useState<string>("");
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
const [sortByOpt, setSortByOpt] = useState<any>(sortBy === "popular" ? "clickCount" : "createdAt");
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
const isRegional = asPath?.includes("regional");
|
const isRegional = asPath?.includes("regional");
|
||||||
const isSatker = asPath?.includes("satker");
|
const isSatker = asPath?.includes("satker");
|
||||||
const [formatFilter, setFormatFilter] = useState<any>([]);
|
const [formatFilter, setFormatFilter] = useState<any>([]);
|
||||||
|
|
@ -106,8 +131,14 @@ const FilterPage = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (categorie) {
|
if (categorie) {
|
||||||
setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
setCategoryFilter(
|
||||||
console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Kategori",
|
||||||
|
categorie,
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [categorie]);
|
}, [categorie]);
|
||||||
|
|
||||||
|
|
@ -125,7 +156,19 @@ const FilterPage = () => {
|
||||||
}
|
}
|
||||||
console.log(monthYearFilter, "monthFilter");
|
console.log(monthYearFilter, "monthFilter");
|
||||||
initState();
|
initState();
|
||||||
}, [change, asPath, monthYearFilter, page, sortBy, sortByOpt, title, startDateString, endDateString, categorie, formatFilter]);
|
}, [
|
||||||
|
change,
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
async function getCategories() {
|
async function getCategories() {
|
||||||
const category = await listCategory("1");
|
const category = await listCategory("1");
|
||||||
|
|
@ -148,7 +191,10 @@ const FilterPage = () => {
|
||||||
async function getDataAll() {
|
async function getDataAll() {
|
||||||
if (asPath?.includes("/polda/") == true) {
|
if (asPath?.includes("/polda/") == true) {
|
||||||
if (asPath?.split("/")[2] !== "[polda_name]") {
|
if (asPath?.split("/")[2] !== "[polda_name]") {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -166,8 +212,14 @@ const FilterPage = () => {
|
||||||
filterGroup,
|
filterGroup,
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)
|
||||||
|
?.split("/")[0]
|
||||||
|
?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -182,7 +234,10 @@ const FilterPage = () => {
|
||||||
setTotalContent(response?.data?.data?.totalElements);
|
setTotalContent(response?.data?.data?.totalElements);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -199,8 +254,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -251,7 +310,10 @@ const FilterPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDataRegional() {
|
async function getDataRegional() {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -264,8 +326,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
12,
|
12,
|
||||||
pages,
|
pages,
|
||||||
sortByOpt
|
sortByOpt
|
||||||
|
|
@ -382,7 +448,10 @@ const FilterPage = () => {
|
||||||
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||||
</svg>`;
|
</svg>`;
|
||||||
|
|
||||||
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
const toBase64 = (str: string) =>
|
||||||
|
typeof window === "undefined"
|
||||||
|
? Buffer.from(str).toString("base64")
|
||||||
|
: window.btoa(str);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
|
|
@ -401,13 +470,16 @@ const FilterPage = () => {
|
||||||
{/* Left */}
|
{/* Left */}
|
||||||
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
||||||
<div className="lg:hidden flex justify-end mb-2">
|
<div className="lg:hidden flex justify-end mb-2">
|
||||||
<button onClick={() => setIsFilterOpen(!isFilterOpen)} className="text-sm text-white bg-[#bb3523] px-4 py-1 rounded-md shadow">
|
<button
|
||||||
|
onClick={() => setIsFilterOpen(!isFilterOpen)}
|
||||||
|
className="text-sm text-white bg-[#bb3523] px-4 py-1 rounded-md shadow"
|
||||||
|
>
|
||||||
{isFilterOpen ? "Hide Filter" : "Show Filter"}
|
{isFilterOpen ? "Hide Filter" : "Show Filter"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isFilterOpen && (
|
{isFilterOpen && (
|
||||||
<div className="lg:w-[25%] h-fit w-full bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
Filter
|
Filter
|
||||||
|
|
@ -415,7 +487,10 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="search" className="block text-sm font-medium text-gray-700 dark:text-white">
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
{t("search")}
|
{t("search")}
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -431,7 +506,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("monthYear")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear")}
|
||||||
|
</label>
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selected={monthYearFilter}
|
selected={monthYearFilter}
|
||||||
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
|
@ -443,7 +520,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("date")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date")}
|
||||||
|
</label>
|
||||||
<div className="flex flex-row justify justify-between gap-2">
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selectsRange
|
selectsRange
|
||||||
|
|
@ -456,18 +535,44 @@ const FilterPage = () => {
|
||||||
placeholderText={t("selectDate")}
|
placeholderText={t("selectDate")}
|
||||||
onCalendarClose={() => setCalenderState(!calenderState)}
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center">{handleClose ? <Icon icon="carbon:close-filled" onClick={handleDeleteDate} width="20" inline color="#216ba5" /> : ""}</div>
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">{t("categories")}</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories")}
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
{categories.map((category: any) => (
|
{categories.map((category: any) => (
|
||||||
<li key={category?.id}>
|
<li key={category?.id}>
|
||||||
<label className="inline-flex items-center" htmlFor={`${category.id}`}>
|
<label
|
||||||
<Checkbox id={`${category.id}`} value={category.id} checked={categoryFilter.includes(String(category.id))} onCheckedChange={(e) => handleCategoryFilter(Boolean(e), category.id)} />
|
className="inline-flex items-center"
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">{category?.name}</span>
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -477,31 +582,63 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
{/* Garis */}
|
{/* Garis */}
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">Format</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="png" value="png" checked={formatFilter.includes("png")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "png")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">PNG</span>
|
id="png"
|
||||||
|
value="png"
|
||||||
|
checked={formatFilter.includes("png")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "png")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
PNG
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="jpeg" value="jpeg" checked={formatFilter.includes("jpeg")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "jpeg")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">JPEG</span>
|
id="jpeg"
|
||||||
|
value="jpeg"
|
||||||
|
checked={formatFilter.includes("jpeg")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "jpeg")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
JPEG
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="jpg" value="jpg" checked={formatFilter.includes("jpg")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "jpg")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">JPG</span>
|
id="jpg"
|
||||||
|
value="jpg"
|
||||||
|
checked={formatFilter.includes("jpg")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "jpg")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
JPG
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-black dark:border-white my-4"></div>
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<a onClick={cleanCheckbox} className="text-[#bb3523] cursor-pointer">
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
<b>Reset Filter</b>
|
<b>Reset Filter</b>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -515,7 +652,11 @@ const FilterPage = () => {
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex flex-col items-end mb-4">
|
<div className="flex flex-col items-end mb-4">
|
||||||
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
||||||
<select defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} onChange={(e) => handleSorting(e)} className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500">
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
|
||||||
|
onChange={(e) => handleSorting(e)}
|
||||||
|
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
>
|
||||||
<option value="latest">{t("latest")}</option>
|
<option value="latest">{t("latest")}</option>
|
||||||
<option value="popular">{t("mostPopular")}</option>
|
<option value="popular">{t("mostPopular")}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -539,13 +680,19 @@ const FilterPage = () => {
|
||||||
{imageData?.length > 0 ? (
|
{imageData?.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{imageData?.map((image: any) => (
|
{imageData?.map((image: any) => (
|
||||||
<Card key={image?.id} className="hover:scale-105 transition-transform duration-300">
|
<Card
|
||||||
|
key={image?.id}
|
||||||
|
className="hover:scale-105 transition-transform duration-300"
|
||||||
|
>
|
||||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||||
<Link href={`/image/detail/${image?.slug}`}>
|
<Link href={`/image/detail/${image?.slug}`}>
|
||||||
{/* <img src={image?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg" /> */}
|
{/* <img src={image?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg" /> */}
|
||||||
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
||||||
<ImageBlurry
|
<ImageBlurry
|
||||||
src={image?.smallThumbnailLink || image?.thumbnailLink}
|
src={
|
||||||
|
image?.smallThumbnailLink ||
|
||||||
|
image?.thumbnailLink
|
||||||
|
}
|
||||||
alt={image?.title}
|
alt={image?.title}
|
||||||
style={{
|
style={{
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
|
|
@ -555,12 +702,21 @@ const FilterPage = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-1 mt-2">
|
<div className="flex flex-row items-center gap-2 text-[10px] mx-1 mt-2">
|
||||||
{formatDateToIndonesian(new Date(image?.createdAt))} {image?.timezone ? image?.timezone : "WIB"}
|
{formatDateToIndonesian(
|
||||||
|
new Date(image?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{image?.timezone ? image?.timezone : "WIB"}
|
||||||
|
|
|
|
||||||
<Icon icon="formkit:eye" width="15" height="15" />
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>
|
||||||
{image?.clickCount}{" "}
|
{image?.clickCount}{" "}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{image?.title}</div>
|
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||||
|
{image?.title}
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -568,12 +724,24 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center text-black">
|
<p className="flex items-center justify-center text-black">
|
||||||
<Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-60 w-60 my-4" />
|
<Image
|
||||||
|
width={1920}
|
||||||
|
height={1080}
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
className="h-60 w-60 my-4"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{totalData > 1 && <LandingPagination table={table} totalData={totalData} totalPage={totalPage} />}
|
{totalData > 1 && (
|
||||||
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,31 @@ import React, { useEffect, useState } from "react";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { formatDateToIndonesian, getOnlyDate, getOnlyMonthAndYear } from "@/utils/globals";
|
import {
|
||||||
|
formatDateToIndonesian,
|
||||||
|
getOnlyDate,
|
||||||
|
getOnlyMonthAndYear,
|
||||||
|
} from "@/utils/globals";
|
||||||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { getListContent, getUserLevelListByParent, listCategory, listData, listDataRegional } from "@/service/landing/landing";
|
import {
|
||||||
import { ColumnDef, ColumnFiltersState, PaginationState, SortingState, VisibilityState, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
getListContent,
|
||||||
|
getUserLevelListByParent,
|
||||||
|
listCategory,
|
||||||
|
listData,
|
||||||
|
listDataRegional,
|
||||||
|
} from "@/service/landing/landing";
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
PaginationState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
useReactTable,
|
||||||
|
} from "@tanstack/react-table";
|
||||||
import LandingPagination from "@/components/landing-page/pagination";
|
import LandingPagination from "@/components/landing-page/pagination";
|
||||||
import { Reveal } from "@/components/landing-page/Reveal";
|
import { Reveal } from "@/components/landing-page/Reveal";
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
|
@ -37,8 +58,11 @@ const FilterPage = () => {
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
[]
|
||||||
|
);
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
React.useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
|
|
@ -56,7 +80,9 @@ const FilterPage = () => {
|
||||||
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
||||||
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||||
const [searchTitle, setSearchTitle] = useState<string>("");
|
const [searchTitle, setSearchTitle] = useState<string>("");
|
||||||
const [sortByOpt, setSortByOpt] = useState<any>(sortBy === "popular" ? "clickCount" : "createdAt");
|
const [sortByOpt, setSortByOpt] = useState<any>(
|
||||||
|
sortBy === "popular" ? "clickCount" : "createdAt"
|
||||||
|
);
|
||||||
const isRegional = asPath?.includes("regional");
|
const isRegional = asPath?.includes("regional");
|
||||||
const isSatker = asPath?.includes("satker");
|
const isSatker = asPath?.includes("satker");
|
||||||
const [formatFilter, setFormatFilter] = useState<any>([]);
|
const [formatFilter, setFormatFilter] = useState<any>([]);
|
||||||
|
|
@ -102,8 +128,14 @@ const FilterPage = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (categorie) {
|
if (categorie) {
|
||||||
setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
setCategoryFilter(
|
||||||
console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Kategori",
|
||||||
|
categorie,
|
||||||
|
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [categorie]);
|
}, [categorie]);
|
||||||
|
|
||||||
|
|
@ -116,7 +148,19 @@ const FilterPage = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initState();
|
initState();
|
||||||
}, [change, asPath, monthYearFilter, page, sortBy, sortByOpt, title, startDateString, endDateString, categorie, formatFilter]);
|
}, [
|
||||||
|
change,
|
||||||
|
asPath,
|
||||||
|
monthYearFilter,
|
||||||
|
page,
|
||||||
|
sortBy,
|
||||||
|
sortByOpt,
|
||||||
|
title,
|
||||||
|
startDateString,
|
||||||
|
endDateString,
|
||||||
|
categorie,
|
||||||
|
formatFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
async function getCategories() {
|
async function getCategories() {
|
||||||
const category = await listCategory("2");
|
const category = await listCategory("2");
|
||||||
|
|
@ -139,7 +183,10 @@ const FilterPage = () => {
|
||||||
async function getDataAll() {
|
async function getDataAll() {
|
||||||
if (asPath?.includes("/polda/") == true) {
|
if (asPath?.includes("/polda/") == true) {
|
||||||
if (asPath?.split("/")[2] !== "[polda_name]") {
|
if (asPath?.split("/")[2] !== "[polda_name]") {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -157,8 +204,14 @@ const FilterPage = () => {
|
||||||
filterGroup,
|
filterGroup,
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)
|
||||||
|
?.split("/")[0]
|
||||||
|
?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -173,7 +226,10 @@ const FilterPage = () => {
|
||||||
setTotalContent(response?.data?.data?.totalElements);
|
setTotalContent(response?.data?.data?.totalElements);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
loading();
|
loading();
|
||||||
|
|
@ -189,8 +245,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
locale == "en" ? true : false
|
locale == "en" ? true : false
|
||||||
);
|
);
|
||||||
close();
|
close();
|
||||||
|
|
@ -241,7 +301,10 @@ const FilterPage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getDataRegional() {
|
async function getDataRegional() {
|
||||||
const filter = categoryFilter?.length > 0 ? categoryFilter?.sort().join(",") : categorie || "";
|
const filter =
|
||||||
|
categoryFilter?.length > 0
|
||||||
|
? categoryFilter?.sort().join(",")
|
||||||
|
: categorie || "";
|
||||||
|
|
||||||
const name = title == undefined ? "" : title;
|
const name = title == undefined ? "" : title;
|
||||||
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
const format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||||
|
|
@ -254,8 +317,12 @@ const FilterPage = () => {
|
||||||
"",
|
"",
|
||||||
startDateString,
|
startDateString,
|
||||||
endDateString,
|
endDateString,
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
monthYearFilter
|
||||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||||
|
: "",
|
||||||
|
monthYearFilter
|
||||||
|
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||||
|
: "",
|
||||||
12,
|
12,
|
||||||
pages,
|
pages,
|
||||||
sortByOpt
|
sortByOpt
|
||||||
|
|
@ -396,7 +463,7 @@ const FilterPage = () => {
|
||||||
|
|
||||||
{/* Left */}
|
{/* Left */}
|
||||||
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
||||||
<div className="lg:w-[25%] w-full bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
<div className="h-fit min-w-full lg:min-w-[280px] max-w-full lg:max-w-[300px] bg-[#f7f7f7] dark:bg-black p-4 rounded-lg shadow-md">
|
||||||
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
<h2 className="text-lg font-semibold mb-4 flex items-center gap-1">
|
||||||
<Icon icon="stash:filter-light" fontSize={30} />
|
<Icon icon="stash:filter-light" fontSize={30} />
|
||||||
Filter
|
Filter
|
||||||
|
|
@ -404,7 +471,10 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor="search" className="block text-sm font-medium text-gray-700 dark:text-white">
|
<label
|
||||||
|
htmlFor="search"
|
||||||
|
className="block text-sm font-medium text-gray-700 dark:text-white"
|
||||||
|
>
|
||||||
{t("search")}
|
{t("search")}
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -420,7 +490,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("monthYear")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("monthYear")}
|
||||||
|
</label>
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selected={monthYearFilter}
|
selected={monthYearFilter}
|
||||||
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
|
@ -432,7 +504,9 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 dark:text-white">{t("date")}</label>
|
<label className="block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("date")}
|
||||||
|
</label>
|
||||||
<div className="flex flex-row justify justify-between gap-2">
|
<div className="flex flex-row justify justify-between gap-2">
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
selectsRange
|
selectsRange
|
||||||
|
|
@ -445,18 +519,44 @@ const FilterPage = () => {
|
||||||
placeholderText={t("selectDate")}
|
placeholderText={t("selectDate")}
|
||||||
onCalendarClose={() => setCalenderState(!calenderState)}
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center">{handleClose ? <Icon icon="carbon:close-filled" onClick={handleDeleteDate} width="20" inline color="#216ba5" /> : ""}</div>
|
<div className="flex items-center">
|
||||||
|
{handleClose ? (
|
||||||
|
<Icon
|
||||||
|
icon="carbon:close-filled"
|
||||||
|
onClick={handleDeleteDate}
|
||||||
|
width="20"
|
||||||
|
inline
|
||||||
|
color="#216ba5"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">{t("categories")}</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
{t("categories")}
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
{categories.map((category: any) => (
|
{categories.map((category: any) => (
|
||||||
<li key={category?.id}>
|
<li key={category?.id}>
|
||||||
<label className="inline-flex items-center" htmlFor={`${category.id}`}>
|
<label
|
||||||
<Checkbox id={`${category.id}`} value={category.id} checked={categoryFilter.includes(String(category.id))} onCheckedChange={(e) => handleCategoryFilter(Boolean(e), category.id)} />
|
className="inline-flex items-center"
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">{category?.name}</span>
|
htmlFor={`${category.id}`}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
id={`${category.id}`}
|
||||||
|
value={category.id}
|
||||||
|
checked={categoryFilter.includes(String(category.id))}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleCategoryFilter(Boolean(e), category.id)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
{category?.name}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -466,43 +566,93 @@ const FilterPage = () => {
|
||||||
<div className="border-t border-black my-4 dark:border-white"></div>
|
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||||
{/* Garis */}
|
{/* Garis */}
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-medium text-gray-700 dark:text-white">Format</h3>
|
<h3 className="text-sm font-medium text-gray-700 dark:text-white">
|
||||||
|
Format
|
||||||
|
</h3>
|
||||||
<ul className="mt-2 space-y-2">
|
<ul className="mt-2 space-y-2">
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="mk4" value="mk4" checked={formatFilter.includes("mk4")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "mk4")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">MK4</span>
|
id="mk4"
|
||||||
|
value="mk4"
|
||||||
|
checked={formatFilter.includes("mk4")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mk4")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MK4
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="mov" value="mov" checked={formatFilter.includes("mov")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "mov")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">MOV</span>
|
id="mov"
|
||||||
|
value="mov"
|
||||||
|
checked={formatFilter.includes("mov")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mov")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MOV
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="mp4" value="mp4" checked={formatFilter.includes("mp4")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "mp4")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">MP4</span>
|
id="mp4"
|
||||||
|
value="mp4"
|
||||||
|
checked={formatFilter.includes("mp4")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "mp4")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
MP4
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="avi" value="avi" checked={formatFilter.includes("avi")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "avi")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">AVI</span>
|
id="avi"
|
||||||
|
value="avi"
|
||||||
|
checked={formatFilter.includes("avi")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "avi")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
AVI
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label className="inline-flex items-center">
|
<label className="inline-flex items-center">
|
||||||
<Checkbox id="wmv" value="wmv" checked={formatFilter.includes("wmv")} onCheckedChange={(e) => handleFormatFilter(Boolean(e), "wmv")} />
|
<Checkbox
|
||||||
<span className="ml-2 text-gray-700 dark:text-white">WMV</span>
|
id="wmv"
|
||||||
|
value="wmv"
|
||||||
|
checked={formatFilter.includes("wmv")}
|
||||||
|
onCheckedChange={(e) =>
|
||||||
|
handleFormatFilter(Boolean(e), "wmv")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span className="ml-2 text-gray-700 dark:text-white">
|
||||||
|
WMV
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-black dark:border-white my-4"></div>
|
<div className="border-t border-black dark:border-white my-4"></div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<a onClick={cleanCheckbox} className="text-[#bb3523] cursor-pointer">
|
<a
|
||||||
|
onClick={cleanCheckbox}
|
||||||
|
className="text-[#bb3523] cursor-pointer"
|
||||||
|
>
|
||||||
<b>Reset Filter</b>
|
<b>Reset Filter</b>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -515,7 +665,11 @@ const FilterPage = () => {
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex flex-col items-end mb-4">
|
<div className="flex flex-col items-end mb-4">
|
||||||
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
<h2 className="text-lg font-semibold">{t("sortBy")}</h2>
|
||||||
<select defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"} onChange={(e) => handleSorting(e)} className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500">
|
<select
|
||||||
|
defaultValue={sortBy == "popular" ? "terpopuler" : "terbaru"}
|
||||||
|
onChange={(e) => handleSorting(e)}
|
||||||
|
className="border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||||
|
>
|
||||||
<option value="latest">{t("latest")}</option>
|
<option value="latest">{t("latest")}</option>
|
||||||
<option value="popular">{t("mostPopular")}</option>
|
<option value="popular">{t("mostPopular")}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -539,18 +693,39 @@ const FilterPage = () => {
|
||||||
{videoData?.length > 0 ? (
|
{videoData?.length > 0 ? (
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{videoData?.map((video: any) => (
|
{videoData?.map((video: any) => (
|
||||||
<Card key={video?.id} className="hover:scale-110 transition-transform duration-300">
|
<Card
|
||||||
|
key={video?.id}
|
||||||
|
className="hover:scale-110 transition-transform duration-300"
|
||||||
|
>
|
||||||
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
<CardContent className="flex flex-col text-xs lg:text-sm w-full p-0">
|
||||||
<Link href={`/video/detail/${video?.slug}`}>
|
<Link href={`/video/detail/${video?.slug}`}>
|
||||||
{/* <img src={video?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */}
|
{/* <img src={video?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg place-self-center" /> */}
|
||||||
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
||||||
<ImageBlurry src={video?.thumbnailLink} alt={video?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} />
|
<ImageBlurry
|
||||||
|
src={video?.thumbnailLink}
|
||||||
|
alt={video?.title}
|
||||||
|
style={{
|
||||||
|
objectFit: "contain",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
|
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
|
||||||
{formatDateToIndonesian(new Date(video?.createdAt))} {video?.timezone ? video?.timezone : "WIB"} | <Icon icon="formkit:eye" width="15" height="15" />
|
{formatDateToIndonesian(
|
||||||
|
new Date(video?.createdAt)
|
||||||
|
)}{" "}
|
||||||
|
{video?.timezone ? video?.timezone : "WIB"} |{" "}
|
||||||
|
<Icon
|
||||||
|
icon="formkit:eye"
|
||||||
|
width="15"
|
||||||
|
height="15"
|
||||||
|
/>
|
||||||
{video?.clickCount}{" "}
|
{video?.clickCount}{" "}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{video?.title}</div>
|
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||||
|
{video?.title}
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
@ -558,13 +733,23 @@ const FilterPage = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center">
|
<p className="flex items-center justify-center">
|
||||||
<Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-60 w-60 my-4" />
|
<Image
|
||||||
|
width={1920}
|
||||||
|
height={1080}
|
||||||
|
src="/assets/empty-data.png"
|
||||||
|
alt="empty"
|
||||||
|
className="h-60 w-60 my-4"
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<LandingPagination table={table} totalData={totalData} totalPage={totalPage} />
|
<LandingPagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Reveal>
|
</Reveal>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { Link } from "@/i18n/routing";
|
import { Link } from "@/i18n/routing";
|
||||||
import { loading } from "@/lib/swal";
|
import { loading } from "@/lib/swal";
|
||||||
import { id } from "date-fns/locale";
|
import { id } from "date-fns/locale";
|
||||||
|
import { htmlToString } from "@/utils/globals";
|
||||||
|
import InfoLainnyaModal from "../ticketing/info-lainnya";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -63,6 +65,7 @@ export default function FormDetailEscalation() {
|
||||||
const [listDiscussion, setListDiscussion] = useState();
|
const [listDiscussion, setListDiscussion] = useState();
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const [selectedPriority, setSelectedPriority] = useState("");
|
const [selectedPriority, setSelectedPriority] = useState("");
|
||||||
|
const [openEmergencyModal, setOpenEmergencyModal] = useState(false);
|
||||||
const [replyMessage, setReplyMessage] = useState("");
|
const [replyMessage, setReplyMessage] = useState("");
|
||||||
const [replies, setReplies] = useState([
|
const [replies, setReplies] = useState([
|
||||||
{
|
{
|
||||||
|
|
@ -136,6 +139,10 @@ export default function FormDetailEscalation() {
|
||||||
setReplyMessage("");
|
setReplyMessage("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openEmergencyIssueDetail = () => {
|
||||||
|
setOpenEmergencyModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
|
@ -179,6 +186,29 @@ export default function FormDetailEscalation() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="p-5 bg-white">{detail.message}</p>
|
<p className="p-5 bg-white">{detail.message}</p>
|
||||||
|
<div className="px-4 py-1 bg-white text-sm">
|
||||||
|
{detail?.typeId === 6 && detail?.emergencyIssue ? (
|
||||||
|
<div className="row mx-0 mb-3 emergency-attachments">
|
||||||
|
<div className=" mr-4">
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
size="md"
|
||||||
|
onClick={openEmergencyIssueDetail}
|
||||||
|
>
|
||||||
|
Info Lainnya
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{detail?.emergencyIssue && (
|
||||||
|
<InfoLainnyaModal
|
||||||
|
open={openEmergencyModal}
|
||||||
|
onClose={() => setOpenEmergencyModal(false)}
|
||||||
|
data={detail.emergencyIssue}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ import {
|
||||||
import { ChevronDownIcon } from "lucide-react";
|
import { ChevronDownIcon } from "lucide-react";
|
||||||
import { getOperatorUser } from "@/service/management-user/management-user";
|
import { getOperatorUser } from "@/service/management-user/management-user";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
|
import { htmlToString } from "@/utils/globals";
|
||||||
|
import InfoLainnyaModal from "../ticketing/info-lainnya";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,8 @@ import { ChevronDownIcon } from "lucide-react";
|
||||||
import { getOperatorUser } from "@/service/management-user/management-user";
|
import { getOperatorUser } from "@/service/management-user/management-user";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
message: z.string().optional(),
|
||||||
description: z.string().min(2, {
|
description: z.string().optional(),
|
||||||
message: "Narasi Penugasan harus lebih dari 2 karakter.",
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type taskDetail = {
|
export type taskDetail = {
|
||||||
|
|
@ -509,7 +507,7 @@ export default function FormQuestionsReply() {
|
||||||
<Label>Judul</Label>
|
<Label>Judul</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="title"
|
name="message"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input
|
<Input
|
||||||
size="md"
|
size="md"
|
||||||
|
|
|
||||||
|
|
@ -683,7 +683,7 @@ export default function FormImageDetail() {
|
||||||
""
|
""
|
||||||
)} */}
|
)} */}
|
||||||
|
|
||||||
{detail?.isPublish == false && detail.isPublishOnPolda == true ? (
|
{(detail?.isPublish == false && detail.isPublishOnPolda == true) || (detail?.isPublish == false && detail?.isInternationalMedia == true && Number(detail?.statusId) == 2) ? (
|
||||||
<div className="flex flex-col gap-2 p-3">
|
<div className="flex flex-col gap-2 p-3">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => publishToMabes()}
|
onClick={() => publishToMabes()}
|
||||||
|
|
@ -952,7 +952,7 @@ export default function FormImageDetail() {
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Card>
|
</Card>
|
||||||
{Number(detail?.needApprovalFromLevel) == Number(userLevelId) ? (
|
{(Number(detail?.needApprovalFromLevel) == Number(userLevelId)) || (detail?.isInternationalMedia == true && detail?.isForwardFromNational == true && Number(detail?.statusId) == 1) ? (
|
||||||
Number(detail?.uploadedById) == Number(userId) ? (
|
Number(detail?.uploadedById) == Number(userId) ? (
|
||||||
""
|
""
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { getUserById } from "@/service/management-user/management-user";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { FileText } from "lucide-react";
|
||||||
|
|
||||||
|
interface Detail {
|
||||||
|
fullname: string;
|
||||||
|
birthPlace: string;
|
||||||
|
birthDate: string;
|
||||||
|
education: string;
|
||||||
|
career: string;
|
||||||
|
expertise: string;
|
||||||
|
experience: string;
|
||||||
|
position: string;
|
||||||
|
region: string;
|
||||||
|
cvUrl: string;
|
||||||
|
photoUrl: string;
|
||||||
|
isActive: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function FormDetailExperts() {
|
||||||
|
const params = useParams();
|
||||||
|
const id = params?.id;
|
||||||
|
const [detail, setDetail] = useState<Detail | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function initState() {
|
||||||
|
if (id) {
|
||||||
|
const response = await getUserById(String(id));
|
||||||
|
const details = response?.data?.data;
|
||||||
|
setDetail(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initState();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
if (!detail) return <div>Loading...</div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="flex flex-col md:flex-row p-4 gap-6">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<Image
|
||||||
|
src={"/assets/img/experts.png"}
|
||||||
|
alt="Profile Picture"
|
||||||
|
width={450}
|
||||||
|
height={850}
|
||||||
|
className="rounded-md object-cover"
|
||||||
|
/>
|
||||||
|
<div className="flex items-start gap-2 mt-2">
|
||||||
|
<span className="text-sm">Not Active</span>
|
||||||
|
<Switch checked={detail.isActive} disabled />
|
||||||
|
<span className="text-sm">Active</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-y-2 w-full">
|
||||||
|
<div>
|
||||||
|
<strong>Nama:</strong> {detail?.fullname}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Tempat / Tanggal Lahir:</strong> {detail.birthPlace},{" "}
|
||||||
|
{detail.birthDate}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Pendidikan:</strong> {detail.education}
|
||||||
|
</div>
|
||||||
|
<div className="sm:col-span-2">
|
||||||
|
<strong>Karier:</strong>
|
||||||
|
<p className="whitespace-pre-line">{detail.career}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Bidang Keahlian:</strong> {detail.expertise}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Pengalaman:</strong> {detail.experience}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Posisi:</strong> {detail.position}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Wilayah:</strong> {detail.region}
|
||||||
|
</div>
|
||||||
|
<div className="sm:col-span-2">
|
||||||
|
<strong>CV:</strong>
|
||||||
|
<div className="mt-1">
|
||||||
|
<Button variant="outline" asChild>
|
||||||
|
<a href={detail.cvUrl} target="_blank" rel="noopener noreferrer">
|
||||||
|
<FileText className="mr-2 h-4 w-4" /> Lihat CV
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const wilayahList = [
|
||||||
|
{ id: "mabes", label: "Mabes" },
|
||||||
|
{ id: "polda", label: "Polda" },
|
||||||
|
{ id: "satker", label: "Satker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
|
export default function DetailSettingTracking() {
|
||||||
|
const t = useTranslations("Menu");
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
wilayah: [] as string[],
|
||||||
|
jumlah: [] as number[],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: any) => {
|
||||||
|
console.log("Submitted values:", values);
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="px-3 py-3">
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
|
{/* Wilayah */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="wilayah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Wilayah</FormLabel>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{wilayahList.map((item) => (
|
||||||
|
<div key={item.id} className="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={field.value.includes(item.id)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const updated = checked
|
||||||
|
? [...field.value, item.id]
|
||||||
|
: field.value.filter((val) => val !== item.id);
|
||||||
|
field.onChange(updated);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="text-sm">{item.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jumlah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
type="number"
|
||||||
|
placeholder="Masukan Nama Iklan"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-end justify-end">
|
||||||
|
<Button type="submit">Tambah Setting</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const wilayahList = [
|
||||||
|
{ id: "mabes", label: "Mabes" },
|
||||||
|
{ id: "polda", label: "Polda" },
|
||||||
|
{ id: "satker", label: "Satker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
|
export default function CreateSettingTracking() {
|
||||||
|
const t = useTranslations("Menu");
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
wilayah: [] as string[],
|
||||||
|
jumlah: [] as number[],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: any) => {
|
||||||
|
console.log("Submitted values:", values);
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="px-3 py-3">
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
|
{/* Wilayah */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="wilayah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Wilayah</FormLabel>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{wilayahList.map((item) => (
|
||||||
|
<div key={item.id} className="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={field.value.includes(item.id)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const updated = checked
|
||||||
|
? [...field.value, item.id]
|
||||||
|
: field.value.filter((val) => val !== item.id);
|
||||||
|
field.onChange(updated);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="text-sm">{item.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jumlah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
type="number"
|
||||||
|
placeholder="Masukan Nama Iklan"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-end justify-end">
|
||||||
|
<Button type="submit">Tambah Setting</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const wilayahList = [
|
||||||
|
{ id: "mabes", label: "Mabes" },
|
||||||
|
{ id: "polda", label: "Polda" },
|
||||||
|
{ id: "satker", label: "Satker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
|
export default function UpdateSettingTracking() {
|
||||||
|
const t = useTranslations("Menu");
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
wilayah: [] as string[],
|
||||||
|
jumlah: [] as number[],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: any) => {
|
||||||
|
console.log("Submitted values:", values);
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="px-3 py-3">
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
|
{/* Wilayah */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="wilayah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Wilayah</FormLabel>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{wilayahList.map((item) => (
|
||||||
|
<div key={item.id} className="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={field.value.includes(item.id)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const updated = checked
|
||||||
|
? [...field.value, item.id]
|
||||||
|
: field.value.filter((val) => val !== item.id);
|
||||||
|
field.onChange(updated);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="text-sm">{item.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jumlah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
type="number"
|
||||||
|
placeholder="Masukan Nama Iklan"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-end justify-end">
|
||||||
|
<Button type="submit">Tambah Setting</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
export type DetailTicket = {
|
export type DetailTicket = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
commentFromUserId: string;
|
commentFromUserId: string;
|
||||||
assignedTeams: string;
|
assignedTeams: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
|
@ -19,7 +21,10 @@ export type DetailTicket = {
|
||||||
feedUrl: string;
|
feedUrl: string;
|
||||||
recommendationName: string;
|
recommendationName: string;
|
||||||
link: string;
|
link: string;
|
||||||
uploadFiles?: string;
|
uploadFiles?: {
|
||||||
|
fileUrl: string;
|
||||||
|
fileName: string;
|
||||||
|
}[];
|
||||||
description: string;
|
description: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
// InfoLainnyaModal.tsx
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
|
@ -6,6 +5,7 @@ import {
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { DetailTicket } from "./info-lainnya-types";
|
import { DetailTicket } from "./info-lainnya-types";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
interface InfoLainnyaModalProps {
|
interface InfoLainnyaModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
|
@ -18,6 +18,34 @@ export default function InfoLainnyaModal({
|
||||||
onClose,
|
onClose,
|
||||||
data,
|
data,
|
||||||
}: InfoLainnyaModalProps) {
|
}: InfoLainnyaModalProps) {
|
||||||
|
const files = data?.uploadFiles || [];
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
setCurrentIndex((prev) => (prev > 0 ? prev - 1 : prev));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
setCurrentIndex((prev) => (prev < files.length - 1 ? prev + 1 : prev));
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentFile = files[currentIndex];
|
||||||
|
const isImage = (fileUrl: string) =>
|
||||||
|
/\.(jpeg|jpg|png|gif|bmp|webp)$/i.test(fileUrl.toLowerCase());
|
||||||
|
|
||||||
|
const getIframeUrl = (fileUrl: string): string => {
|
||||||
|
const lower = fileUrl.toLowerCase();
|
||||||
|
|
||||||
|
// Dokumen ditampilkan melalui Google Docs Viewer
|
||||||
|
if (/\.(pdf|doc|docx|xls|xlsx|ppt|pptx)$/i.test(lower)) {
|
||||||
|
return `https://docs.google.com/viewer?url=${encodeURIComponent(
|
||||||
|
fileUrl
|
||||||
|
)}&embedded=true`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileUrl;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onClose}>
|
<Dialog open={open} onOpenChange={onClose}>
|
||||||
<DialogContent size="md">
|
<DialogContent size="md">
|
||||||
|
|
@ -41,11 +69,11 @@ export default function InfoLainnyaModal({
|
||||||
<div>:{data?.recommendationName}</div>
|
<div>:{data?.recommendationName}</div>
|
||||||
|
|
||||||
<div className="font-medium">Link Pendukung</div>
|
<div className="font-medium">Link Pendukung</div>
|
||||||
<div>
|
<div className="flex">
|
||||||
:
|
:
|
||||||
<a
|
<a
|
||||||
href={data?.link}
|
href={data?.link}
|
||||||
className="text-blue-600"
|
className="text-blue-600 flex w-[100px]"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
|
@ -53,15 +81,43 @@ export default function InfoLainnyaModal({
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data?.uploadFiles && (
|
{files.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="font-medium">Lampiran</div>
|
<div className="font-medium col-span-2">Lampiran</div>
|
||||||
<div>
|
<div className="col-span-2 flex flex-col items-center space-y-2 w-full">
|
||||||
<img
|
{isImage(currentFile?.fileUrl || "") ? (
|
||||||
src={data?.uploadFiles}
|
<img
|
||||||
alt="Lampiran"
|
src={currentFile?.fileUrl}
|
||||||
className="max-w-xs"
|
alt={`Lampiran ${currentIndex + 1}`}
|
||||||
/>
|
className="max-h-[300px] w-auto object-contain border rounded"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<iframe
|
||||||
|
src={getIframeUrl(currentFile?.fileUrl || "")}
|
||||||
|
title={`Lampiran ${currentIndex + 1}`}
|
||||||
|
className="w-full max-w-2xl h-[300px] border rounded"
|
||||||
|
onError={(e) => {
|
||||||
|
(e.target as HTMLIFrameElement).style.display = "none";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<button
|
||||||
|
onClick={handlePrev}
|
||||||
|
disabled={currentIndex === 0}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleNext}
|
||||||
|
disabled={currentIndex === files.length - 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -588,6 +588,7 @@ export default function FormDetailTicketing() {
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={selectedOperator.includes(op.value)}
|
checked={selectedOperator.includes(op.value)}
|
||||||
|
disabled
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
if (e.target.checked) {
|
if (e.target.checked) {
|
||||||
setSelectedOperator((prev) => [
|
setSelectedOperator((prev) => [
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ const regions = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Polda Kalimantan Utara",
|
name: "Polda Kalimantan Utara",
|
||||||
slug: "kaltara",
|
slug: "kalimantan-utara",
|
||||||
logo: "/logo/polda/polda-kaltara.png",
|
logo: "/logo/polda/polda-kalimantan-utara.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Polda Kepulauan Riau",
|
name: "Polda Kepulauan Riau",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,19 @@ import { usePathname } from "next/navigation";
|
||||||
export const DynamicLogoPolda = () => {
|
export const DynamicLogoPolda = () => {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const polda = pathname?.split("/")[3];
|
const polda = pathname?.split("/")[3];
|
||||||
console.log("polda", polda)
|
console.log("polda", polda);
|
||||||
|
|
||||||
return <div className="p-2">{pathname?.includes("/polda") && <Image src={`/logo/polda/polda-${polda}.png`} alt="Logo" width={1920} height={1080} className="object-contain h-[150px] w-[50px]" />}</div>;
|
return (
|
||||||
|
<div className="p-2">
|
||||||
|
{pathname?.includes("/polda") && (
|
||||||
|
<Image
|
||||||
|
src={`/logo/polda/polda-${polda}.png`}
|
||||||
|
alt="Logo"
|
||||||
|
width={1920}
|
||||||
|
height={1080}
|
||||||
|
className="object-contain h-[150px] w-[50px]"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { getCalendarPagination } from "@/service/schedule/schedule";
|
import { getCalendarPagination } from "@/service/schedule/schedule";
|
||||||
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface CalendarItem {
|
interface CalendarItem {
|
||||||
|
|
@ -7,7 +8,7 @@ interface CalendarItem {
|
||||||
description: string;
|
description: string;
|
||||||
assignedTo: string;
|
assignedTo: string;
|
||||||
assignedToLevel: string;
|
assignedToLevel: string;
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
createdById: number;
|
createdById: number;
|
||||||
|
|
@ -18,7 +19,6 @@ interface CalendarItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
const EventCalender = () => {
|
const EventCalender = () => {
|
||||||
// Get current date
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const currentMonth = today.getMonth();
|
const currentMonth = today.getMonth();
|
||||||
const currentYear = today.getFullYear();
|
const currentYear = today.getFullYear();
|
||||||
|
|
@ -26,11 +26,22 @@ const EventCalender = () => {
|
||||||
|
|
||||||
const [events, setEvents] = useState<CalendarItem[]>([]);
|
const [events, setEvents] = useState<CalendarItem[]>([]);
|
||||||
const [selectedEvent, setSelectedEvent] = useState<CalendarItem | null>(null);
|
const [selectedEvent, setSelectedEvent] = useState<CalendarItem | null>(null);
|
||||||
|
const [month, setMonth] = useState(currentMonth);
|
||||||
|
const [year, setYear] = useState(currentYear);
|
||||||
|
|
||||||
// Month names in Indonesian
|
|
||||||
const monthNames = [
|
const monthNames = [
|
||||||
"Januari", "Februari", "Maret", "April", "Mei", "Juni",
|
"Januari",
|
||||||
"Juli", "Agustus", "September", "Oktober", "November", "Desember"
|
"Februari",
|
||||||
|
"Maret",
|
||||||
|
"April",
|
||||||
|
"Mei",
|
||||||
|
"Juni",
|
||||||
|
"Juli",
|
||||||
|
"Agustus",
|
||||||
|
"September",
|
||||||
|
"Oktober",
|
||||||
|
"November",
|
||||||
|
"Desember",
|
||||||
];
|
];
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
|
@ -39,8 +50,6 @@ const EventCalender = () => {
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
const contentData = data?.content;
|
const contentData = data?.content;
|
||||||
setEvents(contentData || []);
|
setEvents(contentData || []);
|
||||||
|
|
||||||
// Set first event as selected by default
|
|
||||||
if (contentData && contentData.length > 0) {
|
if (contentData && contentData.length > 0) {
|
||||||
setSelectedEvent(contentData[0]);
|
setSelectedEvent(contentData[0]);
|
||||||
}
|
}
|
||||||
|
|
@ -48,49 +57,37 @@ const EventCalender = () => {
|
||||||
console.error("Error fetching calendar events:", error);
|
console.error("Error fetching calendar events:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Get first day of the month and number of days
|
const firstDayOfMonth = new Date(year, month, 1);
|
||||||
const firstDayOfMonth = new Date(currentYear, currentMonth, 1);
|
const lastDayOfMonth = new Date(year, month + 1, 0);
|
||||||
const lastDayOfMonth = new Date(currentYear, currentMonth + 1, 0);
|
|
||||||
const daysInMonth = lastDayOfMonth.getDate();
|
const daysInMonth = lastDayOfMonth.getDate();
|
||||||
const startingDayOfWeek = firstDayOfMonth.getDay();
|
const startingDayOfWeek = firstDayOfMonth.getDay();
|
||||||
|
|
||||||
// Convert Sunday (0) to 7 for Monday-first week
|
|
||||||
const adjustedStartingDay = startingDayOfWeek === 0 ? 6 : startingDayOfWeek - 1;
|
const adjustedStartingDay = startingDayOfWeek === 0 ? 6 : startingDayOfWeek - 1;
|
||||||
|
|
||||||
// Generate calendar days
|
|
||||||
const generateCalendarDays = () => {
|
const generateCalendarDays = () => {
|
||||||
const days = [];
|
const days = [];
|
||||||
|
|
||||||
// Empty cells for days before the first day of month
|
|
||||||
for (let i = 0; i < adjustedStartingDay; i++) {
|
for (let i = 0; i < adjustedStartingDay; i++) {
|
||||||
days.push(null);
|
days.push(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Days of the month
|
|
||||||
for (let day = 1; day <= daysInMonth; day++) {
|
for (let day = 1; day <= daysInMonth; day++) {
|
||||||
days.push(day);
|
days.push(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill remaining cells to complete the grid (6 rows × 7 days = 42 cells)
|
|
||||||
while (days.length < 42) {
|
while (days.length < 42) {
|
||||||
days.push(null);
|
days.push(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return days;
|
return days;
|
||||||
};
|
};
|
||||||
|
|
||||||
const calendarDays = generateCalendarDays();
|
const calendarDays = generateCalendarDays();
|
||||||
|
|
||||||
// Helper function to extract day from date string
|
|
||||||
const getDateFromString = (dateString: string) => {
|
const getDateFromString = (dateString: string) => {
|
||||||
try {
|
try {
|
||||||
const date = new Date(dateString);
|
const date = new Date(dateString);
|
||||||
if (date.getMonth() === currentMonth && date.getFullYear() === currentYear) {
|
if (date.getMonth() === month && date.getFullYear() === year) {
|
||||||
return date.getDate();
|
return date.getDate();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -99,17 +96,16 @@ const EventCalender = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function to format date range
|
|
||||||
const formatDateRange = (startDate: string, endDate: string) => {
|
const formatDateRange = (startDate: string, endDate: string) => {
|
||||||
try {
|
try {
|
||||||
const start = new Date(startDate);
|
const start = new Date(startDate);
|
||||||
const end = new Date(endDate);
|
const end = new Date(endDate);
|
||||||
|
|
||||||
const startDay = start.getDate();
|
const startDay = start.getDate();
|
||||||
const endDay = end.getDate();
|
const endDay = end.getDate();
|
||||||
const startMonth = monthNames[start.getMonth()];
|
const startMonth = monthNames[start.getMonth()];
|
||||||
const endMonth = monthNames[end.getMonth()];
|
const endMonth = monthNames[end.getMonth()];
|
||||||
|
|
||||||
if (startDay === endDay && startMonth === endMonth) {
|
if (startDay === endDay && startMonth === endMonth) {
|
||||||
return `${startDay} ${startMonth}`;
|
return `${startDay} ${startMonth}`;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -120,33 +116,49 @@ const EventCalender = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function to format time range
|
|
||||||
const formatTimeRange = (startDate: string, endDate: string) => {
|
const formatTimeRange = (startDate: string, endDate: string) => {
|
||||||
try {
|
try {
|
||||||
const start = new Date(startDate);
|
const start = new Date(startDate);
|
||||||
const end = new Date(endDate);
|
const end = new Date(endDate);
|
||||||
|
|
||||||
const startTime = start.toLocaleTimeString('id-ID', {
|
const startTime = start.toLocaleTimeString("id-ID", {
|
||||||
hour: '2-digit',
|
hour: "2-digit",
|
||||||
minute: '2-digit',
|
minute: "2-digit",
|
||||||
timeZone: 'Asia/Jakarta'
|
timeZone: "Asia/Jakarta",
|
||||||
});
|
});
|
||||||
const endTime = end.toLocaleTimeString('id-ID', {
|
const endTime = end.toLocaleTimeString("id-ID", {
|
||||||
hour: '2-digit',
|
hour: "2-digit",
|
||||||
minute: '2-digit',
|
minute: "2-digit",
|
||||||
timeZone: 'Asia/Jakarta'
|
timeZone: "Asia/Jakarta",
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${startTime} - ${endTime} WIB`;
|
return `${startTime} - ${endTime} WIB`;
|
||||||
} catch {
|
} catch {
|
||||||
return "Waktu tidak tersedia";
|
return "Waktu tidak tersedia";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get event dates for highlighting calendar
|
|
||||||
const eventDates = events
|
const eventDates = events
|
||||||
.map(event => getDateFromString(event.startDate))
|
.map((event) => getDateFromString(event.startDate))
|
||||||
.filter(date => date !== null);
|
.filter((date) => date !== null);
|
||||||
|
|
||||||
|
const handlePreviousMonth = () => {
|
||||||
|
if (month === 0) {
|
||||||
|
setMonth(11);
|
||||||
|
setYear((y) => y - 1);
|
||||||
|
} else {
|
||||||
|
setMonth((m) => m - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNextMonth = () => {
|
||||||
|
if (month === 11) {
|
||||||
|
setMonth(0);
|
||||||
|
setYear((y) => y + 1);
|
||||||
|
} else {
|
||||||
|
setMonth((m) => m + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-8 rounded-lg bg-white dark:bg-zinc-900 p-4 shadow">
|
<div className="mt-8 rounded-lg bg-white dark:bg-zinc-900 p-4 shadow">
|
||||||
|
|
@ -154,12 +166,18 @@ const EventCalender = () => {
|
||||||
KALENDER ACARA
|
KALENDER ACARA
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex flex-col lg:flex-row gap-6">
|
<div className="flex flex-col lg:flex-row gap-6">
|
||||||
{/* Left Side - Calendar and Event List */}
|
|
||||||
<div className="w-full lg:w-1/2">
|
<div className="w-full lg:w-1/2">
|
||||||
{/* Mini Calendar */}
|
|
||||||
<div className="bg-gray-100 dark:bg-zinc-800 p-4 rounded-md mb-4">
|
<div className="bg-gray-100 dark:bg-zinc-800 p-4 rounded-md mb-4">
|
||||||
<div className="text-center font-semibold mb-2">
|
<div className="flex items-center justify-between mb-2">
|
||||||
{monthNames[currentMonth]} {currentYear}
|
<button onClick={handlePreviousMonth}>
|
||||||
|
<ChevronLeft className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
|
<div className="text-center font-semibold">
|
||||||
|
{monthNames[month]} {year}
|
||||||
|
</div>
|
||||||
|
<button onClick={handleNextMonth}>
|
||||||
|
<ChevronRight className="w-4 h-4" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-7 gap-1 text-sm text-center">
|
<div className="grid grid-cols-7 gap-1 text-sm text-center">
|
||||||
{["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((d) => (
|
{["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"].map((d) => (
|
||||||
|
|
@ -167,26 +185,32 @@ const EventCalender = () => {
|
||||||
{d}
|
{d}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{calendarDays?.map((day, index) => (
|
{calendarDays.map((day, index) => {
|
||||||
<div
|
const isToday =
|
||||||
key={index}
|
day === currentDate &&
|
||||||
className={`p-1 rounded min-h-[24px] flex items-center justify-center text-xs ${
|
month === currentMonth &&
|
||||||
day === null
|
year === currentYear;
|
||||||
? ""
|
|
||||||
: eventDates.includes(day)
|
return (
|
||||||
? "bg-red-600 text-white font-semibold"
|
<div
|
||||||
: day === currentDate
|
key={index}
|
||||||
? "bg-blue-500 text-white font-semibold"
|
className={`p-1 rounded min-h-[24px] flex items-center justify-center text-xs ${
|
||||||
: "hover:bg-gray-200 dark:hover:bg-zinc-700"
|
day === null
|
||||||
}`}
|
? ""
|
||||||
>
|
: eventDates.includes(day)
|
||||||
{day}
|
? "bg-red-600 text-white font-semibold"
|
||||||
</div>
|
: isToday
|
||||||
))}
|
? "bg-blue-500 text-white font-semibold"
|
||||||
|
: "hover:bg-gray-200 dark:hover:bg-zinc-700"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{day}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Event List */}
|
|
||||||
<div className="space-y-3 max-h-[230px] overflow-y-auto pr-5" data-lenis-prevent>
|
<div className="space-y-3 max-h-[230px] overflow-y-auto pr-5" data-lenis-prevent>
|
||||||
<h3 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-3">
|
<h3 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-3">
|
||||||
Daftar Acara
|
Daftar Acara
|
||||||
|
|
@ -224,7 +248,11 @@ const EventCalender = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-2 flex-shrink-0">
|
<div className="ml-2 flex-shrink-0">
|
||||||
<div className={`w-2 h-2 rounded-full ${event.isActive ? 'bg-green-500' : 'bg-red-500'}`}></div>
|
<div
|
||||||
|
className={`w-2 h-2 rounded-full ${
|
||||||
|
event.isActive ? "bg-green-500" : "bg-red-500"
|
||||||
|
}`}
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
|
@ -232,13 +260,12 @@ const EventCalender = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Side - Event Detail */}
|
|
||||||
<div className="w-full lg:w-1/2">
|
<div className="w-full lg:w-1/2">
|
||||||
<div className="bg-gray-100 dark:bg-zinc-800 rounded-lg p-4 sticky top-4">
|
<div className="bg-gray-100 dark:bg-zinc-800 rounded-lg p-4 sticky top-4">
|
||||||
<h3 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-4">
|
<h3 className="text-lg font-semibold text-gray-800 dark:text-gray-200 mb-4">
|
||||||
Detail Acara
|
Detail Acara
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{selectedEvent ? (
|
{selectedEvent ? (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<img
|
<img
|
||||||
|
|
@ -250,16 +277,23 @@ const EventCalender = () => {
|
||||||
target.src = "/images/default-event.png";
|
target.src = "/images/default-event.png";
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-lg font-bold text-gray-800 dark:text-gray-200 mb-2">
|
<h4 className="text-lg font-bold text-gray-800 dark:text-gray-200 mb-2">
|
||||||
{selectedEvent.title}
|
{selectedEvent.title}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 gap-3 mb-4">
|
<div className="grid grid-cols-1 gap-3 mb-4">
|
||||||
<div className="flex items-start text-sm text-gray-600 dark:text-gray-400">
|
<div className="flex items-start text-sm text-gray-600 dark:text-gray-400">
|
||||||
<span className="w-20 font-semibold flex-shrink-0">Tanggal:</span>
|
<span className="w-20 font-semibold flex-shrink-0">
|
||||||
<span>{formatDateRange(selectedEvent.startDate, selectedEvent.endDate)}</span>
|
Tanggal:
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{formatDateRange(
|
||||||
|
selectedEvent.startDate,
|
||||||
|
selectedEvent.endDate
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
|
<p className="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
|
||||||
|
|
@ -267,7 +301,7 @@ const EventCalender = () => {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button className="px-4 py-2 bg-gray-300 dark:bg-zinc-700 text-gray-700 dark:text-gray-300 text-sm font-medium rounded-lg hover:bg-gray-400 dark:hover:bg-zinc-600 transition-colors">
|
<button className="px-4 py-2 bg-gray-300 dark:bg-zinc-700 text-gray-700 dark:text-gray-300 text-sm font-medium rounded-lg hover:bg-gray-400 dark:hover:bg-zinc-600 transition-colors">
|
||||||
Bagikan
|
Bagikan
|
||||||
|
|
@ -277,7 +311,7 @@ const EventCalender = () => {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-center text-gray-500 dark:text-gray-400 py-8">
|
<div className="text-center text-gray-500 dark:text-gray-400 py-8">
|
||||||
Pilih acara untuk melihat detail
|
Pilih acara untuk melihat detail
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -287,4 +321,4 @@ const EventCalender = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EventCalender;
|
export default EventCalender;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import Image from "next/image";
|
||||||
const HeaderBannerSatker = () => {
|
const HeaderBannerSatker = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
const satkerName: any = params?.satker_name;
|
const satkerName: any = params?.satker_name;
|
||||||
const asPath: any = usePathname();
|
const asPath: any = usePathname();
|
||||||
const [content, setContent] = useState([]);
|
const [content, setContent] = useState([]);
|
||||||
|
|
@ -50,7 +51,7 @@ const HeaderBannerSatker = () => {
|
||||||
);
|
);
|
||||||
var data = res?.data?.data?.content;
|
var data = res?.data?.data?.content;
|
||||||
if (data) {
|
if (data) {
|
||||||
const resStatic = await listStaticBanner(satkerName, false);
|
const resStatic = await listStaticBanner(satkerName, locale == "en");
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
media.fileTypeId = media.fileType?.id;
|
media.fileTypeId = media.fileType?.id;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import { useRouter } from "@/i18n/routing";
|
||||||
const HeaderBanner = () => {
|
const HeaderBanner = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
const poldaName: any = params?.polda_name;
|
const poldaName: any = params?.polda_name;
|
||||||
const [content, setContent] = useState([]);
|
const [content, setContent] = useState([]);
|
||||||
const [isBannerLoading, setIsBannerLoading] = useState(true);
|
const [isBannerLoading, setIsBannerLoading] = useState(true);
|
||||||
|
|
@ -31,7 +32,7 @@ const HeaderBanner = () => {
|
||||||
const res = await listData("1", "", "", 5, 0, "createdAt", "", "", poldaName);
|
const res = await listData("1", "", "", 5, 0, "createdAt", "", "", poldaName);
|
||||||
var data = res?.data?.data?.content;
|
var data = res?.data?.data?.content;
|
||||||
if (data) {
|
if (data) {
|
||||||
const resStatic = await listStaticBanner(poldaName, false);
|
const resStatic = await listStaticBanner(poldaName, locale == "en");
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
media.fileTypeId = media.fileType?.id;
|
media.fileTypeId = media.fileType?.id;
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ const HeroModal = ({ onClose, group, poldaName, satkerName }: HeroModalProps) =>
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
if (group === "polda" && poldaName && String(poldaName).length > 1) {
|
if (group === "polda" && poldaName && String(poldaName).length > 1) {
|
||||||
const response = await listStaticBanner(poldaName);
|
const response = await listStaticBanner(poldaName, locale == "en");
|
||||||
|
|
||||||
const banners =
|
const banners =
|
||||||
response?.data?.data?.map((item: any) => {
|
response?.data?.data?.map((item: any) => {
|
||||||
|
|
@ -245,13 +245,13 @@ const HeroNewPolda = (props: { group?: string }) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
setHeroData(data);
|
setHeroData(data);
|
||||||
|
|
||||||
if (data && props.group === "polda" && poldaName && String(poldaName)?.length > 1) {
|
if (data && props.group === "polda" && poldaName && String(poldaName)?.length > 1) {
|
||||||
const resStatic = await listStaticBanner(poldaName);
|
const resStatic = await listStaticBanner(poldaName, locale == "en");
|
||||||
|
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ const HeroModal = ({ onClose, group, poldaName, satkerName }: HeroModalProps) =>
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
if (group === "satker" && satkerName && String(satkerName).length > 1) {
|
if (group === "satker" && satkerName && String(satkerName).length > 1) {
|
||||||
const response = await listStaticBanner(satkerName);
|
const response = await listStaticBanner(satkerName, locale == "en");
|
||||||
|
|
||||||
const banners =
|
const banners =
|
||||||
response?.data?.data?.map((item: any) => {
|
response?.data?.data?.map((item: any) => {
|
||||||
|
|
@ -245,13 +245,13 @@ const HeroNewSatker = (props: { group?: string }) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
setHeroData(data);
|
setHeroData(data);
|
||||||
|
|
||||||
if (data && props.group === "satker" && satkerName && String(satkerName)?.length > 1) {
|
if (data && props.group === "satker" && satkerName && String(satkerName)?.length > 1) {
|
||||||
const resStatic = await listStaticBanner(satkerName);
|
const resStatic = await listStaticBanner(satkerName, locale == "en");
|
||||||
|
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,8 @@ const HeroModal = ({
|
||||||
? poldaName
|
? poldaName
|
||||||
: group === "satker" && satkerName && String(satkerName)?.length > 1
|
: group === "satker" && satkerName && String(satkerName)?.length > 1
|
||||||
? "satker-" + satkerName
|
? "satker-" + satkerName
|
||||||
: ""
|
: "",
|
||||||
|
locale == "en"
|
||||||
);
|
);
|
||||||
|
|
||||||
const banners =
|
const banners =
|
||||||
|
|
@ -295,7 +296,7 @@ const HeroNew = (props: { group?: string }) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
setHeroData(response?.data?.data?.content);
|
setHeroData(response?.data?.data?.content);
|
||||||
|
|
@ -309,7 +310,8 @@ const HeroNew = (props: { group?: string }) => {
|
||||||
satkerName &&
|
satkerName &&
|
||||||
String(satkerName)?.length > 1
|
String(satkerName)?.length > 1
|
||||||
? "satker-" + satkerName
|
? "satker-" + satkerName
|
||||||
: ""
|
: "",
|
||||||
|
locale == "en"
|
||||||
);
|
);
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
|
|
|
||||||
|
|
@ -79,11 +79,11 @@ const HeroModal = ({ onClose }: { onClose: () => void }) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
if (data) {
|
if (data) {
|
||||||
const resStatic = await listStaticBanner();
|
const resStatic = await listStaticBanner("", locale == "en");
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
media.fileTypeId = media.fileType?.id;
|
media.fileTypeId = media.fileType?.id;
|
||||||
|
|
@ -287,7 +287,7 @@ const Hero = (props: { group?: string }) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
setHeroData(response?.data?.data?.content);
|
setHeroData(response?.data?.data?.content);
|
||||||
|
|
@ -301,7 +301,8 @@ const Hero = (props: { group?: string }) => {
|
||||||
satkerName &&
|
satkerName &&
|
||||||
String(satkerName)?.length > 1
|
String(satkerName)?.length > 1
|
||||||
? "satker-" + satkerName
|
? "satker-" + satkerName
|
||||||
: ""
|
: "",
|
||||||
|
locale == "en"
|
||||||
);
|
);
|
||||||
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
const media = resStatic?.data.data[i]?.mediaUpload;
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,19 @@ import { formatDateToIndonesian, textEllipsis } from "@/utils/globals";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Icon } from "../ui/icon";
|
import { Icon } from "../ui/icon";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
export default function NewsTicker() {
|
export default function NewsTicker() {
|
||||||
const [article, setArticle] = useState<any>([]);
|
const [article, setArticle] = useState<any>([]);
|
||||||
const [currentNewsIndex, setCurrentNewsIndex] = useState<any>(0);
|
const [currentNewsIndex, setCurrentNewsIndex] = useState<any>(0);
|
||||||
const [animate, setAnimate] = useState(false);
|
const [animate, setAnimate] = useState(false);
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
const t = useTranslations("LandingPage");
|
const t = useTranslations("LandingPage");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function getArticle() {
|
async function getArticle() {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
setArticle(response?.data?.data?.content);
|
setArticle(response?.data?.data?.content);
|
||||||
}
|
}
|
||||||
getArticle();
|
getArticle();
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ const ScrollableContentPolda = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ const ScrollableContentPolda = () => {
|
||||||
<div className="">
|
<div className="">
|
||||||
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
|
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
|
||||||
<span className="text-[#c03724] dark:text-white">
|
<span className="text-[#c03724] dark:text-white">
|
||||||
{t("welcome")} Polda {poldaName?.replace("-", " ")}
|
{t("welcome")} Polda {poldaName?.replace("-", " ").toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
{/* <span className="text-[#c03724] dark:text-white">
|
{/* <span className="text-[#c03724] dark:text-white">
|
||||||
{t("download")} {t("coverage")}
|
{t("download")} {t("coverage")}
|
||||||
|
|
@ -63,7 +63,7 @@ const ScrollableContentPolda = () => {
|
||||||
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
||||||
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
||||||
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">
|
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">
|
||||||
{t("officialPolda")} {poldaName?.replace("-", " ")}
|
{t("officialPolda")} {poldaName?.replace("-", " ").toUpperCase()}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-6 flex flex-col md:flex-row justify-center gap-4">
|
<div className="mt-6 flex flex-col md:flex-row justify-center gap-4">
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,14 @@ import { useParams, useRouter } from "next/navigation";
|
||||||
import router from "next/router";
|
import router from "next/router";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "../ui/select";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { getHeroData } from "@/service/landing/landing";
|
import { getHeroData } from "@/service/landing/landing";
|
||||||
import { title } from "process";
|
import { title } from "process";
|
||||||
|
|
@ -43,7 +50,7 @@ const ScrollableContentSatker = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
|
|
||||||
|
|
@ -54,7 +61,7 @@ const ScrollableContentSatker = () => {
|
||||||
<div className="">
|
<div className="">
|
||||||
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
|
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
|
||||||
<span className="text-[#c03724] dark:text-white">
|
<span className="text-[#c03724] dark:text-white">
|
||||||
{t("welcome")} Polda {satkerName?.replace("-", " ")}
|
{t("welcome")} {satkerName?.replace("-", " ").toUpperCase()}
|
||||||
</span>
|
</span>
|
||||||
{/* <span className="text-[#c03724] dark:text-white">
|
{/* <span className="text-[#c03724] dark:text-white">
|
||||||
{t("download")} {t("coverage")}
|
{t("download")} {t("coverage")}
|
||||||
|
|
@ -63,7 +70,7 @@ const ScrollableContentSatker = () => {
|
||||||
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
||||||
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
||||||
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">
|
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">
|
||||||
{t("officialPolda")} {satkerName?.replace("-", " ")}
|
{t("officialSatker")} {satkerName?.replace("-", " ").toUpperCase()}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="mt-6 flex flex-col md:flex-row justify-center gap-4">
|
<div className="mt-6 flex flex-col md:flex-row justify-center gap-4">
|
||||||
|
|
@ -71,7 +78,14 @@ const ScrollableContentSatker = () => {
|
||||||
<Select value={contentType} onValueChange={setContentType}>
|
<Select value={contentType} onValueChange={setContentType}>
|
||||||
<SelectTrigger className="w-[180px] h-[55px]">
|
<SelectTrigger className="w-[180px] h-[55px]">
|
||||||
<span className="text-black">
|
<span className="text-black">
|
||||||
<svg className="mx-2 dark:" width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg
|
||||||
|
className="mx-2 dark:"
|
||||||
|
width="25"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 25 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
d="M20 7.5H5C4.6023 7.5004 4.221 7.65856 3.93978 7.93978C3.65856 8.221 3.5004 8.6023 3.5 9V19.5C3.5004 19.8977 3.65856 20.279 3.93978 20.5602C4.221 20.8414 4.6023 20.9996 5 21H20C20.3977 20.9996 20.779 20.8414 21.0602 20.5602C21.3414 20.279 21.4996 19.8977 21.5 19.5V9C21.4996 8.6023 21.3414 8.221 21.0602 7.93978C20.779 7.65856 20.3977 7.5004 20 7.5ZM10.25 17.25V11.25L15.5 14.25L10.25 17.25ZM5 4.5H20V6H5V4.5ZM6.5 1.5H18.5V3H6.5V1.5Z"
|
d="M20 7.5H5C4.6023 7.5004 4.221 7.65856 3.93978 7.93978C3.65856 8.221 3.5004 8.6023 3.5 9V19.5C3.5004 19.8977 3.65856 20.279 3.93978 20.5602C4.221 20.8414 4.6023 20.9996 5 21H20C20.3977 20.9996 20.779 20.8414 21.0602 20.5602C21.3414 20.279 21.4996 19.8977 21.5 19.5V9C21.4996 8.6023 21.3414 8.221 21.0602 7.93978C20.779 7.65856 20.3977 7.5004 20 7.5ZM10.25 17.25V11.25L15.5 14.25L10.25 17.25ZM5 4.5H20V6H5V4.5ZM6.5 1.5H18.5V3H6.5V1.5Z"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
|
|
@ -92,17 +106,32 @@ const ScrollableContentSatker = () => {
|
||||||
</Select>
|
</Select>
|
||||||
<div className="flex items-center flex-1 border border-gray-300 rounded-lg overflow-hidden">
|
<div className="flex items-center flex-1 border border-gray-300 rounded-lg overflow-hidden">
|
||||||
<span className="material-icons text-black dark:text-white px-4">
|
<span className="material-icons text-black dark:text-white px-4">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="1em"
|
||||||
|
height="1em"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="m19.6 21l-6.3-6.3q-.75.6-1.725.95T9.5 16q-2.725 0-4.612-1.888T3 9.5t1.888-4.612T9.5 3t4.613 1.888T16 9.5q0 1.1-.35 2.075T14.7 13.3l6.3 6.3zM9.5 14q1.875 0 3.188-1.312T14 9.5t-1.312-3.187T9.5 5T6.313 6.313T5 9.5t1.313 3.188T9.5 14"
|
d="m19.6 21l-6.3-6.3q-.75.6-1.725.95T9.5 16q-2.725 0-4.612-1.888T3 9.5t1.888-4.612T9.5 3t4.613 1.888T16 9.5q0 1.1-.35 2.075T14.7 13.3l6.3 6.3zM9.5 14q1.875 0 3.188-1.312T14 9.5t-1.312-3.187T9.5 5T6.313 6.313T5 9.5t1.313 3.188T9.5 14"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
<input type="text" placeholder={t("searchCoverageHere")} className="w-full py-4 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none" onChange={(e) => setSearch(e.target.value)} />
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder={t("searchCoverageHere")}
|
||||||
|
className="w-full py-4 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none"
|
||||||
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button onClick={() => router.push(`/${contentType}/filter?title=${search}`)} className="flex justify-center items-center px-6 w-full lg:w-[20%] py-4 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700">
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/${contentType}/filter?title=${search}`)
|
||||||
|
}
|
||||||
|
className="flex justify-center items-center px-6 w-full lg:w-[20%] py-4 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700"
|
||||||
|
>
|
||||||
{t("searchCoverage")}
|
{t("searchCoverage")}
|
||||||
<Icon icon="ri:arrow-right-s-line" fontSize={20} />
|
<Icon icon="ri:arrow-right-s-line" fontSize={20} />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ const ScrollableContent = () => {
|
||||||
const locale = params?.locale;
|
const locale = params?.locale;
|
||||||
const t = useTranslations("LandingPage");
|
const t = useTranslations("LandingPage");
|
||||||
const [content, setContent] = useState<any>();
|
const [content, setContent] = useState<any>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchCategories() {
|
async function fetchCategories() {
|
||||||
const url = "https://netidhub.com/api/csrf";
|
const url = "https://netidhub.com/api/csrf";
|
||||||
|
|
@ -45,12 +46,13 @@ const ScrollableContent = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const initFetch = async () => {
|
const initFetch = async () => {
|
||||||
const response = await getHeroData();
|
const response = await getHeroData(locale == "en");
|
||||||
console.log(response);
|
console.log(response);
|
||||||
let data = response?.data?.data?.content;
|
let data = response?.data?.data?.content;
|
||||||
|
|
||||||
setContent(data);
|
setContent(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="">
|
<div className="">
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const SearchSectionPolda = () => {
|
||||||
<NewContent group="polda" type="latest" />
|
<NewContent group="polda" type="latest" />
|
||||||
<NewContent group="polda" type="popular" />
|
<NewContent group="polda" type="popular" />
|
||||||
<ContentCategory group="polda" type="popular" />
|
<ContentCategory group="polda" type="popular" />
|
||||||
<AreaCoverageWorkUnits />
|
{/* <AreaCoverageWorkUnits /> */}
|
||||||
<EventCalender />
|
<EventCalender />
|
||||||
<UserSurveyBox />
|
<UserSurveyBox />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ const SearchSectionSatker = () => {
|
||||||
<NewContent group="satker" type="latest" />
|
<NewContent group="satker" type="latest" />
|
||||||
<NewContent group="satker" type="popular" />
|
<NewContent group="satker" type="popular" />
|
||||||
<ContentCategory group="satker" type="popular" />
|
<ContentCategory group="satker" type="popular" />
|
||||||
<AreaCoverageWorkUnits />
|
{/* <AreaCoverageWorkUnits /> */}
|
||||||
<EventCalender />
|
<EventCalender />
|
||||||
<UserSurveyBox />
|
<UserSurveyBox />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -281,17 +281,17 @@ const LoginForm = () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const msg = response?.data?.message;
|
const msg = response?.data?.message;
|
||||||
onSubmit(data);
|
// onSubmit(data);
|
||||||
|
|
||||||
// if (msg == "Continue to setup email") {
|
if (msg == "Continue to setup email") {
|
||||||
// setStep(2);
|
setStep(2);
|
||||||
// } else if (msg == "Email is valid and OTP has been sent") {
|
} else if (msg == "Email is valid and OTP has been sent") {
|
||||||
// setStep(3);
|
setStep(3);
|
||||||
// } else if (msg == "Username & password valid") {
|
} else if (msg == "Username & password valid") {
|
||||||
// onSubmit(data);
|
onSubmit(data);
|
||||||
// } else {
|
} else {
|
||||||
// error("Username / password incorrect");
|
error("Username / password incorrect");
|
||||||
// }
|
}
|
||||||
// else {
|
// else {
|
||||||
// setStep(1);
|
// setStep(1);
|
||||||
// }
|
// }
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
|
|
||||||
let menusSelected = <any>[];
|
let menusSelected = <any>[];
|
||||||
|
|
||||||
if (Number(roleId) == 3 && Number(levelNumber) == 1) {
|
if ((Number(roleId) == 3 || Number(roleId) == 14) && Number(levelNumber) == 1) {
|
||||||
menusSelected = [
|
menusSelected = [
|
||||||
{
|
{
|
||||||
groupLabel: t("apps"),
|
groupLabel: t("apps"),
|
||||||
|
|
@ -1700,7 +1700,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
} else if (
|
} else if (
|
||||||
(Number(roleId) == 3 || Number(roleId) == 4) &&
|
(Number(roleId) == 3 || Number(roleId) == 4 || Number(roleId) == 14 || Number(roleId) == 15) &&
|
||||||
Number(levelNumber) == 2
|
Number(levelNumber) == 2
|
||||||
) {
|
) {
|
||||||
if (Number(userLevelId) != 761) {
|
if (Number(userLevelId) != 761) {
|
||||||
|
|
@ -2158,7 +2158,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
(Number(roleId) == 3 || Number(roleId) == 4) &&
|
(Number(roleId) == 3 || Number(roleId) == 4 || Number(roleId) == 14 || Number(roleId) == 15) &&
|
||||||
Number(levelNumber) == 3
|
Number(levelNumber) == 3
|
||||||
) {
|
) {
|
||||||
if (Number(userParentLevelId) != 761) {
|
if (Number(userParentLevelId) != 761) {
|
||||||
|
|
|
||||||
|
|
@ -364,6 +364,7 @@
|
||||||
"coverage": "Our Official Coverage",
|
"coverage": "Our Official Coverage",
|
||||||
"officialCoverage": "Official coverage sourced from Polri activities at the National Police Headquarters and Regional Police throughout Indonesia",
|
"officialCoverage": "Official coverage sourced from Polri activities at the National Police Headquarters and Regional Police throughout Indonesia",
|
||||||
"officialPolda": "Official Coverage Sourced From Police Activities At Polda",
|
"officialPolda": "Official Coverage Sourced From Police Activities At Polda",
|
||||||
|
"officialSatker": "Official Coverage Sourced From Police Activities At",
|
||||||
"allContent": "All Content",
|
"allContent": "All Content",
|
||||||
"searchCoverage": "Search Coverage",
|
"searchCoverage": "Search Coverage",
|
||||||
"newContent": "Latest Content",
|
"newContent": "Latest Content",
|
||||||
|
|
|
||||||
|
|
@ -364,6 +364,7 @@
|
||||||
"coverage": "LIPUTAN RESMI KAMI",
|
"coverage": "LIPUTAN RESMI KAMI",
|
||||||
"officialCoverage": "Liputan resmi yang bersumber dari kegiatan Polri di Mabes dan Polda seluruh Indonesia",
|
"officialCoverage": "Liputan resmi yang bersumber dari kegiatan Polri di Mabes dan Polda seluruh Indonesia",
|
||||||
"officialPolda": "Liputan Resmi Yang Bersumber Dari Kegiatan Polri Di Polda",
|
"officialPolda": "Liputan Resmi Yang Bersumber Dari Kegiatan Polri Di Polda",
|
||||||
|
"officialSatker": "Liputan Resmi Yang Bersumber Dari Kegiatan Polri Di",
|
||||||
"allContent": "Semua Konten",
|
"allContent": "Semua Konten",
|
||||||
"searchCoverage": "Cari Liputan",
|
"searchCoverage": "Cari Liputan",
|
||||||
"searchCoverageHere": "Cari Liputan Disini",
|
"searchCoverageHere": "Cari Liputan Disini",
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
|
@ -47,22 +47,23 @@ export async function listDataAll(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listDataImage(
|
export async function listDataImage(
|
||||||
size: any,
|
size: any = "",
|
||||||
page: any,
|
page: any = "",
|
||||||
isForSelf: any,
|
isForSelf: any = "",
|
||||||
isApproval: any,
|
isApproval: any = "",
|
||||||
categoryFilter: any,
|
categoryFilter: any = "",
|
||||||
statusFilter: any,
|
statusFilter: any = "",
|
||||||
needApprovalFromLevel: any,
|
needApprovalFromLevel: any = "",
|
||||||
creator: any,
|
creator: any = "",
|
||||||
source: any,
|
source: any = "",
|
||||||
startDate: any,
|
startDate: any = "",
|
||||||
endDate: any,
|
endDate: any = "",
|
||||||
title: string = "",
|
title: string = "",
|
||||||
creatorGroup: string = ""
|
creatorGroup: string = "",
|
||||||
|
isInt: boolean = false
|
||||||
) {
|
) {
|
||||||
return await httpGetInterceptor(
|
return await httpGetInterceptor(
|
||||||
`media/list?enablePage=1&size=${size}&sortBy=createdAt&sort=desc&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}&creatorGroupLevelName=${creatorGroup}`
|
`media/list?enablePage=1&size=${size}&sortBy=createdAt&sort=desc&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}&title=${title}&creatorGroupLevelName=${creatorGroup}&needApprovalFromLevel=${needApprovalFromLevel}&isInt=${isInt}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,9 @@ export async function getCsrfToken() {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getHeroData() {
|
export async function getHeroData(isInt: Boolean = false) {
|
||||||
return await httpGetInterceptor(
|
return await httpGetInterceptor(
|
||||||
`media/public/list?enablePage=1&sort=desc&sortBy=createdAt&size=5&page=0&typeId=1&title=&categoryId=&fileFormats=&tags=&group=&startDate=&endDate=&month=&year=`
|
`media/public/list?enablePage=1&sort=desc&sortBy=createdAt&size=5&page=0&typeId=1&title=&categoryId=&fileFormats=&tags=&group=&startDate=&endDate=&month=&year=&isInt=${isInt}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue