Merge branch 'main' of https://gitlab.com/hanifsalafi/mediahub_redesign into prod
This commit is contained in:
commit
f854cb7385
|
|
@ -13,6 +13,10 @@ import { Button } from "@/components/ui/button";
|
|||
import { Badge } from "@/components/ui/badge";
|
||||
|
||||
import { Link, useRouter } from "@/i18n/routing";
|
||||
import { close, error, loading, success } from "@/config/swal";
|
||||
import { deleteMediaBlastCampaign } from "@/service/broadcast/broadcast";
|
||||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
|
|
@ -62,6 +66,34 @@ const columns: ColumnDef<any>[] = [
|
|||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
||||
const handleDelete = (id: any) => {
|
||||
MySwal.fire({
|
||||
title: "Apakah anda ingin menghapus data?",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#dc3545",
|
||||
confirmButtonText: "Iya",
|
||||
cancelButtonText: "Tidak",
|
||||
}).then((result: any) => {
|
||||
if (result.isConfirmed) {
|
||||
doDeleteAccount(id);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
async function doDeleteAccount(id: any) {
|
||||
loading();
|
||||
const response = await deleteMediaBlastCampaign(id);
|
||||
close();
|
||||
if (response.error) {
|
||||
error(response.message);
|
||||
return false;
|
||||
}
|
||||
// success();
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ const ContentListBanner = () => {
|
|||
checked={selectedItems.length === data.length}
|
||||
onCheckedChange={handleSelectAll}
|
||||
/>
|
||||
<span>Pilih Semua</span>
|
||||
<span className="text-black dark:text-white">Pilih Semua</span>
|
||||
</div>
|
||||
{selectedItems.length > 0 && (
|
||||
<Button color="primary" onClick={() => handleBanner(selectedItems)}>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export default function AdminBanner() {
|
|||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<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 dark:bg-black p-4 rounded-sm space-y-3">
|
||||
<div className="flex justify-between">
|
||||
{selectedTab === "content" ? "List Media" : " List Banner"}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,11 +162,11 @@ export default function EditCategoryModal(props: {
|
|||
}, [id]);
|
||||
|
||||
function removeAndReturn(inputString: string, toRemove: number[]) {
|
||||
const numbers = inputString.split(",").map(Number);
|
||||
const numbers = inputString?.split(",").map(Number);
|
||||
|
||||
const filteredNumbers = numbers.filter((num) => !toRemove.includes(num));
|
||||
const filteredNumbers = numbers?.filter((num) => !toRemove?.includes(num));
|
||||
|
||||
return filteredNumbers.map(String);
|
||||
return filteredNumbers?.map(String);
|
||||
}
|
||||
|
||||
function filterString(inputString: string, type: string) {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ const ImageCreatePage = async () => {
|
|||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<FormImage />
|
||||
<div className="space-y-4 ">
|
||||
<FormImage />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
Trash2,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
|
|
@ -21,9 +22,33 @@ import withReactContent from "sweetalert2-react-content";
|
|||
import Swal from "sweetalert2";
|
||||
|
||||
const useTableColumns = () => {
|
||||
const t = useTranslations("Table"); // Panggil di dalam hook
|
||||
const t = useTranslations("Table");
|
||||
const MySwal = withReactContent(Swal);
|
||||
|
||||
const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
id: "select",
|
||||
header: ({ table }) => (
|
||||
<Checkbox
|
||||
checked={
|
||||
table.getIsAllPageRowsSelected() ||
|
||||
(table.getIsSomePageRowsSelected() && "indeterminate")
|
||||
}
|
||||
onCheckedChange={(val) => table.toggleAllPageRowsSelected(!!val)}
|
||||
aria-label="Pilih semua pada halaman ini"
|
||||
/>
|
||||
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<Checkbox
|
||||
checked={row.getIsSelected()}
|
||||
onCheckedChange={(val) => row.toggleSelected(!!val)}
|
||||
aria-label="Pilih baris"
|
||||
/>
|
||||
),
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: t("no", { defaultValue: "No" }),
|
||||
|
|
@ -56,7 +81,6 @@ const useTableColumns = () => {
|
|||
<span className="whitespace-nowrap">{row.getValue("contentTag")}</span>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "contentType",
|
||||
header: t("type-content", { defaultValue: "Type Content" }),
|
||||
|
|
@ -73,7 +97,6 @@ const useTableColumns = () => {
|
|||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "isPublish",
|
||||
header: "Status",
|
||||
|
|
@ -95,7 +118,6 @@ const useTableColumns = () => {
|
|||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "contentCreatedDate",
|
||||
header: t("upload-date", { defaultValue: "Upload Date" }),
|
||||
|
|
@ -104,7 +126,6 @@ const useTableColumns = () => {
|
|||
| string
|
||||
| number
|
||||
| undefined;
|
||||
|
||||
const formattedDate =
|
||||
createdAt && !isNaN(new Date(createdAt).getTime())
|
||||
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
|
||||
|
|
@ -118,8 +139,7 @@ const useTableColumns = () => {
|
|||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
const isDisabled = row.original.isPublish; // Check the isPublish value
|
||||
|
||||
const isDisabled = row.original.isPublish;
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild disabled={isDisabled}>
|
||||
|
|
@ -128,7 +148,7 @@ const useTableColumns = () => {
|
|||
className={`bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent ${
|
||||
isDisabled ? "cursor-not-allowed opacity-50" : ""
|
||||
}`}
|
||||
disabled={isDisabled} // Disable button if isPublish is true
|
||||
disabled={isDisabled}
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
|
|
@ -142,7 +162,7 @@ const useTableColumns = () => {
|
|||
className={`p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none ${
|
||||
isDisabled ? "cursor-not-allowed opacity-50" : ""
|
||||
}`}
|
||||
disabled={isDisabled} // Disable dropdown item if isPublish is true
|
||||
disabled={isDisabled}
|
||||
>
|
||||
<MoveDownRight className="w-4 h-4 me-1.5" />
|
||||
Pindah Ke Mediahub
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ const FilterPage = () => {
|
|||
<Link href={`/image/detail/${image?.slug}`}>
|
||||
{/* <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">
|
||||
<ImageBlurry
|
||||
{/* <ImageBlurry
|
||||
src={
|
||||
image?.smallThumbnailLink ||
|
||||
image?.thumbnailLink
|
||||
|
|
@ -834,6 +834,16 @@ const FilterPage = () => {
|
|||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
/> */}
|
||||
<Image
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={
|
||||
image?.smallThumbnailLink ||
|
||||
image?.thumbnailLink
|
||||
}
|
||||
alt={image?.title}
|
||||
className="w-full h-full object-cover rounded-t-lg"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-1 mt-2">
|
||||
|
|
|
|||
|
|
@ -833,7 +833,7 @@ const FilterPage = () => {
|
|||
<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" /> */}
|
||||
<div className="img-container h-60 bg-[#e9e9e9] cursor-pointer rounded-lg">
|
||||
<ImageBlurry
|
||||
{/* <ImageBlurry
|
||||
src={
|
||||
video?.smallThumbnailLink ||
|
||||
video?.thumbnailLink
|
||||
|
|
@ -844,6 +844,16 @@ const FilterPage = () => {
|
|||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
/> */}
|
||||
<Image
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={
|
||||
video?.smallThumbnailLink ||
|
||||
video?.thumbnailLink
|
||||
}
|
||||
alt={video?.title}
|
||||
className="w-full h-full object-cover rounded-t-lg"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-2 text-[10px] mx-2">
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ export default function FormImage() {
|
|||
"image/png": [],
|
||||
"image/jpg": [],
|
||||
},
|
||||
multiple: true,
|
||||
onDrop: (acceptedFiles) => {
|
||||
const validFiles = acceptedFiles
|
||||
.filter(
|
||||
|
|
@ -187,8 +188,11 @@ export default function FormImage() {
|
|||
return;
|
||||
}
|
||||
|
||||
setFiles(validFiles);
|
||||
setValue("files", validFiles);
|
||||
setFiles((prev) => {
|
||||
const next = [...prev, ...validFiles];
|
||||
setValue("files", next, { shouldDirty: true });
|
||||
return next;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -1167,12 +1171,13 @@ export default function FormImage() {
|
|||
render={({ field: { onChange, value } }) =>
|
||||
isLoadingData ? (
|
||||
<div className="flex justify-center items-center h-40">
|
||||
<p className="text-gray-500">
|
||||
<p className="text-gray-500 dark:text-black">
|
||||
Loading Proses Data...
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<CustomEditor
|
||||
className="dark:text-black"
|
||||
onChange={(value: any) => {
|
||||
onChange(value);
|
||||
setEditorContent(value);
|
||||
|
|
@ -1498,8 +1503,8 @@ export default function FormImage() {
|
|||
}
|
||||
}
|
||||
|
||||
field.onChange(updated);
|
||||
setPublishedFor(updated);
|
||||
field.onChange(updated);
|
||||
setPublishedFor(updated);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { useSearchParams, useParams } from "next/navigation";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link"; // pastikan path-nya sesuai
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
|
|
@ -12,7 +11,7 @@ import {
|
|||
CarouselPrevious,
|
||||
} from "@/components/ui/carousel";
|
||||
import { getIndeksData, getIndeksDataFilter } from "@/service/landing/landing";
|
||||
import { usePathname, useRouter } from "@/i18n/routing";
|
||||
import { Link, usePathname, useRouter } from "@/i18n/routing";
|
||||
import { loading } from "@/lib/swal";
|
||||
import { getOnlyMonthAndYear } from "@/utils/globals";
|
||||
|
||||
|
|
@ -34,8 +33,8 @@ export default function IndeksCarouselComponent(props: {
|
|||
const asPath = usePathname();
|
||||
const params = useParams();
|
||||
const searchParams = useSearchParams();
|
||||
const [indeksData, setIndeksData] = useState<any[]>([]); // ✅ State untuk menyimpan konten data
|
||||
const [newContent, setNewContent] = useState<any[]>([]); // Optional, bisa jadi redundant
|
||||
const [indeksData, setIndeksData] = useState<any[]>([]);
|
||||
const [newContent, setNewContent] = useState<any[]>([]);
|
||||
const [totalData, setTotalData] = useState<number>(0);
|
||||
const [totalPage, setTotalPage] = useState<number>(0);
|
||||
const [totalContent, setTotalContent] = useState<number>(0);
|
||||
|
|
@ -111,81 +110,53 @@ export default function IndeksCarouselComponent(props: {
|
|||
]);
|
||||
|
||||
async function initFetch() {
|
||||
if (asPath?.includes("/polda/") == true) {
|
||||
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 filterGroup = group == undefined ? asPath.split("/")[2] : group;
|
||||
loading();
|
||||
const response = await getIndeksDataFilter(
|
||||
"4",
|
||||
name,
|
||||
filter,
|
||||
12,
|
||||
0,
|
||||
sortByOpt,
|
||||
"",
|
||||
"",
|
||||
filterGroup,
|
||||
startDateString,
|
||||
endDateString,
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)
|
||||
?.split("/")[0]
|
||||
?.replace("", "")
|
||||
: "",
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||
: ""
|
||||
);
|
||||
close();
|
||||
const data = response?.data?.data;
|
||||
const contentData = data?.content;
|
||||
setNewContent(contentData);
|
||||
setTotalData(data?.totalElements);
|
||||
setTotalPage(data?.totalPages);
|
||||
setTotalContent(response?.data?.data?.totalElements);
|
||||
}
|
||||
} else {
|
||||
const filter =
|
||||
categoryFilter?.length > 0
|
||||
? categoryFilter?.sort().join(",")
|
||||
: categorie || "";
|
||||
const name = title ?? "";
|
||||
const month = monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||
: "";
|
||||
const year = monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||
: "";
|
||||
|
||||
const name = title == undefined ? "" : title;
|
||||
// Gunakan group hanya jika asPath mengandung /polda/ atau /satker/, selain itu kosongkan
|
||||
let filterGroup = "";
|
||||
if (asPath.includes("/polda/") || asPath.includes("/satker/")) {
|
||||
filterGroup = group ?? asPath.split("/")[2];
|
||||
}
|
||||
|
||||
try {
|
||||
loading();
|
||||
const response = await getIndeksDataFilter(
|
||||
"4",
|
||||
name,
|
||||
filter,
|
||||
12,
|
||||
0,
|
||||
sortByOpt,
|
||||
"",
|
||||
"",
|
||||
"4", // type
|
||||
name, // title
|
||||
filter, // kategori
|
||||
12, // size
|
||||
0, // page
|
||||
sortByOpt, // sortBy
|
||||
"",
|
||||
"", // provinceId, cityId
|
||||
filterGroup, // group
|
||||
startDateString,
|
||||
endDateString,
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||
: "",
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||
: ""
|
||||
month,
|
||||
year
|
||||
);
|
||||
close();
|
||||
|
||||
const data = response?.data?.data;
|
||||
const contentData = data?.content;
|
||||
|
||||
setNewContent(contentData);
|
||||
setTotalData(data?.totalElements);
|
||||
setTotalPage(data?.totalPages);
|
||||
setTotalContent(response?.data?.data?.totalElements);
|
||||
setNewContent(contentData || []);
|
||||
setTotalData(data?.totalElements || 0);
|
||||
setTotalPage(data?.totalPages || 0);
|
||||
setTotalContent(data?.totalElements || 0);
|
||||
} catch (error) {
|
||||
close();
|
||||
console.error("Error fetching indeks data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +201,7 @@ export default function IndeksCarouselComponent(props: {
|
|||
</Carousel>
|
||||
<div className="flex justify-center mt-1 mb-6">
|
||||
<Link
|
||||
href={`${prefixPath}/image`}
|
||||
href={`${prefixPath}/indeks`}
|
||||
className="border border-red-500 text-red-500 hover:bg-red-500 text-sm hover:text-white px-4 py-2 rounded transition duration-200"
|
||||
>
|
||||
Lihat Semua
|
||||
|
|
|
|||
|
|
@ -726,17 +726,16 @@ const Navbar = () => {
|
|||
{/* Inbox */}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<a className="cursor-pointer" onClick={() => test()}>
|
||||
<a
|
||||
className="cursor-pointer text-black dark:text-white"
|
||||
onClick={() => test()}
|
||||
>
|
||||
{" "}
|
||||
<Icon
|
||||
icon="basil:envelope-outline"
|
||||
color="black"
|
||||
width="30"
|
||||
/>
|
||||
<Icon icon="basil:envelope-outline" width="30" />
|
||||
</a>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className=" p-0 h-32 flex flex-col mt-2"
|
||||
className="overflow-y-scroll p-0 h-full flex flex-col mt-2"
|
||||
align="end"
|
||||
>
|
||||
<Tabs
|
||||
|
|
@ -1214,6 +1213,15 @@ const Navbar = () => {
|
|||
</a>
|
||||
</div>
|
||||
|
||||
{/* Languange */}
|
||||
<div
|
||||
className={`${
|
||||
isHidden ? "hidden" : "custom-lg-button:flex"
|
||||
} relative text-left`}
|
||||
>
|
||||
<LocalSwitcher />
|
||||
</div>
|
||||
|
||||
<div className="relative inline-block mx-3 text-left">
|
||||
<ThemeSwitcher />
|
||||
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ const NewContent = (props: { group: string; type: string }) => {
|
|||
{[
|
||||
{ label: t("image", { defaultValue: "Image" }), value: "image" },
|
||||
{ label: t("video", { defaultValue: "Video" }), value: "video" },
|
||||
{ label: t("text", { defaultValue: "Text" }), value: "text" },
|
||||
{ label: t("text", { defaultValue: "Text" }), value: "document" },
|
||||
{ label: t("audio", { defaultValue: "Audio" }), value: "audio" },
|
||||
].map((tab) => (
|
||||
<TabsTrigger
|
||||
|
|
@ -591,11 +591,11 @@ const NewContent = (props: { group: string; type: string }) => {
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* <div className="flex items-center flex-row justify-center">
|
||||
<div onClick={() => router.push(prefixPath + `/${selectedTab}/filter?sortBy=${props.type}`)} className="cursor-pointer border text-[#bb3523] rounded-lg text-sm lg:text-md px-4 py-1 border-[#bb3523]">
|
||||
<div className="flex items-center flex-row justify-center mt-3">
|
||||
<div onClick={() => router.push(prefixPath + `/${selectedTab}/filter?sortBy=${props.type}`)} className="cursor-pointer border text-[#bb3523] rounded-lg text-sm lg:text-md px-4 py-1 border-[#bb3523] hover:text-white hover:bg-[#bb3523]">
|
||||
{t("seeAll", { defaultValue: "See All" })}
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ export async function getMediaBlastCampaignList() {
|
|||
return httpGetInterceptor(url);
|
||||
}
|
||||
|
||||
export async function deleteMediaBlastCampaign(id: string | number): Promise<any> {
|
||||
const url = `media/blast/campaign?id=${id}`;
|
||||
return httpDeleteInterceptor({ url });
|
||||
}
|
||||
|
||||
export async function detailMediaSummary(id: string) {
|
||||
const url = `media?id=${id}&isSummary=true`;
|
||||
return httpGetInterceptor(url);
|
||||
|
|
|
|||
Loading…
Reference in New Issue