QUDO 30-33
This commit is contained in:
parent
fbc0db0ab4
commit
ffda2700c6
|
|
@ -12,6 +12,7 @@ import SearchSectionKaltara from "@/components/landing-page/landing-polda-kaltar
|
|||
import LatestContentKaltara from "@/components/landing-page/landing-polda-kaltara/latest-content-kaltara";
|
||||
import ContactUsKaltara from "@/components/landing-page/landing-polda-kaltara/contact-us-kaltara";
|
||||
import NewsTickerKaltara from "../../tbnews/[polda_name]/components/news-tickers-kaltara";
|
||||
import ContentCategoryKaltara from "@/components/landing-page/landing-polda-kaltara/content-category-kaltara";
|
||||
|
||||
const page = () => {
|
||||
const params = useParams();
|
||||
|
|
@ -24,7 +25,7 @@ const page = () => {
|
|||
<WelcomePolda />
|
||||
<LatestContentKaltara group="polda" type="latest" />
|
||||
<LatestContentKaltara group="polda" type="popular" />
|
||||
<ContentCategory group="polda" />
|
||||
<ContentCategoryKaltara type="" group="polda" />
|
||||
<ContactUsKaltara />
|
||||
<NewsTickerKaltara />
|
||||
</div>
|
||||
|
|
@ -34,7 +35,7 @@ const page = () => {
|
|||
<WelcomePolda />
|
||||
<NewContent group="polda" type="latest" />
|
||||
<NewContent group="polda" type="popular" />
|
||||
<ContentCategory group="polda" />
|
||||
<ContentCategory type="" group="polda" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,14 +27,6 @@ export default function FilterPage() {
|
|||
const [imageData, setImageData] = useState<any>();
|
||||
const [totalData, setTotalData] = React.useState<number>(1);
|
||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = useState(1);
|
||||
const [totalContent, setTotalContent] = useState();
|
||||
const [change, setChange] = useState(false);
|
||||
|
|
@ -157,7 +149,7 @@ export default function FilterPage() {
|
|||
setImageData(contentData);
|
||||
setTotalData(data?.totalElements);
|
||||
setContentAll(response?.data?.data?.content);
|
||||
setTotalPage(data?.totalPages);
|
||||
setTotalPage(response?.data?.data?.totalPages);
|
||||
setTotalContent(response?.data?.data?.totalElements);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -187,7 +179,7 @@ export default function FilterPage() {
|
|||
setImageData(contentData);
|
||||
setTotalData(data?.totalElements);
|
||||
setContentAll(response?.data?.data?.content);
|
||||
setTotalPage(data?.totalPages);
|
||||
setTotalPage(response?.data?.data?.totalPages);
|
||||
setTotalContent(response?.data?.data?.totalElements);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ const FilterPage = () => {
|
|||
</div>
|
||||
<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">
|
||||
{formatDateToIndonesian(new Date(document?.createdAt))} {document?.timezone ? document?.timezone : "WIB"} | <Icon icon="formkit:eye" width="15" height="15" /> 518
|
||||
{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 className="flex gap-2 items-center text-xs text-red-500 dark:text-red-500">
|
||||
|
|
|
|||
|
|
@ -3,30 +3,10 @@ import React, { useEffect, useState } from "react";
|
|||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
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 {
|
||||
getUserLevelListByParent,
|
||||
listCategory,
|
||||
listData,
|
||||
listDataRegional,
|
||||
} from "@/service/landing/landing";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { 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 { Reveal } from "@/components/landing-page/Reveal";
|
||||
import { Link, useRouter } from "@/i18n/routing";
|
||||
|
|
@ -58,11 +38,8 @@ const FilterPage = () => {
|
|||
const [totalData, setTotalData] = React.useState<number>(1);
|
||||
const [totalPage, setTotalPage] = React.useState<number>(1);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
||||
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
|
|
@ -83,9 +60,7 @@ const FilterPage = () => {
|
|||
const [categoryFilter, setCategoryFilter] = useState<any>([]);
|
||||
const [monthYearFilter, setMonthYearFilter] = useState<any>();
|
||||
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 isSatker = asPath?.includes("satker");
|
||||
const [formatFilter, setFormatFilter] = useState<any>([]);
|
||||
|
|
@ -131,14 +106,8 @@ const FilterPage = () => {
|
|||
|
||||
useEffect(() => {
|
||||
if (categorie) {
|
||||
setCategoryFilter(
|
||||
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||
);
|
||||
console.log(
|
||||
"Kategori",
|
||||
categorie,
|
||||
categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]
|
||||
);
|
||||
setCategoryFilter(categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
||||
console.log("Kategori", categorie, categorie?.split("&")?.length > 1 ? categorie?.split("&") : [categorie]);
|
||||
}
|
||||
}, [categorie]);
|
||||
|
||||
|
|
@ -156,19 +125,7 @@ const FilterPage = () => {
|
|||
}
|
||||
console.log(monthYearFilter, "monthFilter");
|
||||
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() {
|
||||
const category = await listCategory("1");
|
||||
|
|
@ -191,10 +148,7 @@ const FilterPage = () => {
|
|||
async function getDataAll() {
|
||||
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 format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||
|
|
@ -212,14 +166,8 @@ const FilterPage = () => {
|
|||
filterGroup,
|
||||
startDateString,
|
||||
endDateString,
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)
|
||||
?.split("/")[0]
|
||||
?.replace("", "")
|
||||
: "",
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||
: "",
|
||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
||||
locale == "en" ? true : false
|
||||
);
|
||||
close();
|
||||
|
|
@ -234,10 +182,7 @@ const FilterPage = () => {
|
|||
setTotalContent(response?.data?.data?.totalElements);
|
||||
}
|
||||
} 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 format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||
|
|
@ -254,12 +199,8 @@ const FilterPage = () => {
|
|||
"",
|
||||
startDateString,
|
||||
endDateString,
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||
: "",
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||
: "",
|
||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
||||
locale == "en" ? true : false
|
||||
);
|
||||
close();
|
||||
|
|
@ -310,10 +251,7 @@ const FilterPage = () => {
|
|||
};
|
||||
|
||||
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 format = formatFilter == undefined ? "" : formatFilter?.join(",");
|
||||
|
|
@ -326,12 +264,8 @@ const FilterPage = () => {
|
|||
"",
|
||||
startDateString,
|
||||
endDateString,
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "")
|
||||
: "",
|
||||
monthYearFilter
|
||||
? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1]
|
||||
: "",
|
||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[0]?.replace("", "") : "",
|
||||
monthYearFilter ? getOnlyMonthAndYear(monthYearFilter)?.split("/")[1] : "",
|
||||
12,
|
||||
pages,
|
||||
sortByOpt
|
||||
|
|
@ -448,10 +382,7 @@ const FilterPage = () => {
|
|||
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||
</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 (
|
||||
<div className="flex flex-col">
|
||||
|
|
@ -470,10 +401,7 @@ const FilterPage = () => {
|
|||
{/* Left */}
|
||||
<div className="flex flex-col lg:flex-row gap-6 p-4">
|
||||
<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"}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -487,10 +415,7 @@ const FilterPage = () => {
|
|||
<div className="border-t border-black my-4 dark:border-white"></div>
|
||||
<div className="space-y-6">
|
||||
<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")}
|
||||
</label>
|
||||
<Input
|
||||
|
|
@ -506,9 +431,7 @@ const FilterPage = () => {
|
|||
</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
|
||||
selected={monthYearFilter}
|
||||
className="mt-1 w-full text-xs border rounded-md py-2 px-3 focus:ring-red-500 focus:border-red-500"
|
||||
|
|
@ -520,9 +443,7 @@ const FilterPage = () => {
|
|||
</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">
|
||||
<ReactDatePicker
|
||||
selectsRange
|
||||
|
|
@ -535,44 +456,18 @@ const FilterPage = () => {
|
|||
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 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>
|
||||
<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 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>
|
||||
))}
|
||||
|
|
@ -582,63 +477,31 @@ const FilterPage = () => {
|
|||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</li>
|
||||
<li>
|
||||
<label className="inline-flex items-center">
|
||||
<Checkbox
|
||||
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>
|
||||
<Checkbox 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>
|
||||
</li>
|
||||
<li>
|
||||
<label className="inline-flex items-center">
|
||||
<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>
|
||||
<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>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="border-t border-black dark:border-white my-4"></div>
|
||||
<div className="text-center">
|
||||
<a
|
||||
onClick={cleanCheckbox}
|
||||
className="text-[#bb3523] cursor-pointer"
|
||||
>
|
||||
<a onClick={cleanCheckbox} className="text-[#bb3523] cursor-pointer">
|
||||
<b>Reset Filter</b>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -652,11 +515,7 @@ const FilterPage = () => {
|
|||
<div className="w-full">
|
||||
<div className="flex flex-col items-end mb-4">
|
||||
<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="popular">{t("mostPopular")}</option>
|
||||
</select>
|
||||
|
|
@ -680,10 +539,7 @@ const FilterPage = () => {
|
|||
{imageData?.length > 0 ? (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{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">
|
||||
<Link href={`/image/detail/${image?.slug}`}>
|
||||
{/* <img src={image?.thumbnailLink} className="h-60 object-cover items-center justify-center cursor-pointer rounded-lg" /> */}
|
||||
|
|
@ -699,32 +555,12 @@ const FilterPage = () => {
|
|||
/>
|
||||
</div>
|
||||
<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}{" "}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
fill="#f00"
|
||||
d="M7.707 10.293a1 1 0 1 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l3-3a1 1 0 0 0-1.414-1.414L11 11.586V6h5a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h5v5.586zM9 4a1 1 0 0 1 2 0v2H9z"
|
||||
/>
|
||||
</svg>{" "}
|
||||
</div>
|
||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">
|
||||
{image?.title}
|
||||
</div>
|
||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{image?.title}</div>
|
||||
</Link>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -732,24 +568,12 @@ const FilterPage = () => {
|
|||
</div>
|
||||
) : (
|
||||
<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>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{totalData > 1 && (
|
||||
<LandingPagination
|
||||
table={table}
|
||||
totalData={totalData}
|
||||
totalPage={totalPage}
|
||||
/>
|
||||
)}
|
||||
{totalData > 1 && <LandingPagination table={table} totalData={totalData} totalPage={totalPage} />}
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -547,14 +547,8 @@ const FilterPage = () => {
|
|||
<ImageBlurry src={video?.thumbnailLink} alt={video?.title} style={{ objectFit: "contain", width: "100%", height: "100%" }} />
|
||||
</div>
|
||||
<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}{" "}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20">
|
||||
<path
|
||||
fill="#f00"
|
||||
d="M7.707 10.293a1 1 0 1 0-1.414 1.414l3 3a1 1 0 0 0 1.414 0l3-3a1 1 0 0 0-1.414-1.414L11 11.586V6h5a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h5v5.586zM9 4a1 1 0 0 1 2 0v2H9z"
|
||||
/>
|
||||
</svg>{" "}
|
||||
</div>
|
||||
<div className="font-semibold pr-3 pb-3 mx-2 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible w-full">{video?.title}</div>
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,13 @@
|
|||
import {
|
||||
getCategoryData,
|
||||
getPublicCategoryData,
|
||||
} from "@/service/landing/landing";
|
||||
import Link from "next/link";
|
||||
import { getCategoryData, getPublicCategoryData } from "@/service/landing/landing";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Button } from "../ui/button";
|
||||
import { Reveal } from "./Reveal";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useParams } from "next/navigation";
|
||||
import Image from "next/image";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselNext,
|
||||
CarouselPrevious,
|
||||
} from "../ui/carousel";
|
||||
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "../ui/carousel";
|
||||
import { useRouter } from "@/i18n/routing";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const ContentCategory = (props: { group?: string; type: string }) => {
|
||||
const [categories, setCategories] = useState<any>();
|
||||
|
|
@ -29,26 +19,14 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
|||
const satkerName = params?.satker_name;
|
||||
const router = useRouter();
|
||||
|
||||
let prefixPath = poldaName
|
||||
? `/polda/${poldaName}`
|
||||
: satkerName
|
||||
? `/satker/${satkerName}`
|
||||
: "/";
|
||||
let prefixPath = poldaName ? `/polda/${poldaName}` : satkerName ? `/satker/${satkerName}` : "/";
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
}, []);
|
||||
const initFetch = async () => {
|
||||
const response = await getPublicCategoryData(
|
||||
props.group == "mabes"
|
||||
? ""
|
||||
: props.group == "polda" && poldaName && String(poldaName)?.length > 1
|
||||
? poldaName
|
||||
: props.group == "satker" &&
|
||||
satkerName &&
|
||||
String(satkerName)?.length > 1
|
||||
? "satker-" + satkerName
|
||||
: "",
|
||||
props.group == "mabes" ? "" : props.group == "polda" && poldaName && String(poldaName)?.length > 1 ? poldaName : props.group == "satker" && satkerName && String(satkerName)?.length > 1 ? "satker-" + satkerName : "",
|
||||
"",
|
||||
locale == "en" ? true : false
|
||||
);
|
||||
|
|
@ -74,10 +52,7 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
|||
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||
</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 (
|
||||
<div className="px-4 lg:px-24 py-10">
|
||||
|
|
@ -85,63 +60,54 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
|||
<h2 className="text-center text-xl lg:text-3xl font-bold text-[#bb3523] mb-4">
|
||||
{pathname?.split("/")[1] == "in" ? (
|
||||
<>
|
||||
<span className="text-black dark:text-white">
|
||||
{t("category")}
|
||||
</span>
|
||||
<span className="text-black dark:text-white">{t("category")} </span>
|
||||
{t("content")}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-black dark:text-white">
|
||||
{t("content")}
|
||||
</span>
|
||||
<span className="text-black dark:text-white">{t("content")} </span>
|
||||
{t("category")}
|
||||
</>
|
||||
)}
|
||||
</h2>
|
||||
<div className="h-1 w-52 bg-[#bb3523] mx-auto mb-6 rounded"></div>
|
||||
|
||||
<div className="">
|
||||
<Carousel className="w-full max-w-full">
|
||||
<CarouselContent>
|
||||
{categories?.map((category: any) => (
|
||||
<CarouselItem key={category?.id} className="md:basis-1/2 lg:basis-1/3">
|
||||
<div onClick={() => router.push(prefixPath + `all/filter?category=${category?.id}`)} className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block">
|
||||
{/* Gambar */}
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||
shimmer(700, 475)
|
||||
)}`}
|
||||
alt="category"
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={category?.thumbnailLink}
|
||||
className="w-full lg:h-[250px] h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
<div className="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{(seeAllValue ? categories : categories?.slice(0, 4 ))?.map((category: any) => (
|
||||
<div key={category?.id}>
|
||||
<div onClick={() => router.push(`${prefixPath}all/filter?category=${category?.id}`)} className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block">
|
||||
{/* Gambar */}
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
|
||||
alt="category"
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={category?.thumbnailLink}
|
||||
className="w-full lg:h-[250px] h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
|
||||
{/* Overlay gelap */}
|
||||
<div className="absolute inset-0 bg-black bg-opacity-25 group-hover:bg-opacity-35 transition-all duration-300 rounded-md"></div>
|
||||
{/* Overlay gelap */}
|
||||
<div className="absolute inset-0 bg-black bg-opacity-25 group-hover:bg-opacity-35 transition-all duration-300 rounded-md"></div>
|
||||
|
||||
{/* Judul */}
|
||||
<div className="absolute bottom-5 left-0 right-16 bg-transparent backdrop-blur-md text-white p-4 border-l-2 border-[#bb3523] z-10 group-hover:scale-x-150 origin-left">
|
||||
<h3 className="text-sm font-semibold truncate">
|
||||
{category?.name}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
<CarouselPrevious className="-ml-0 lg:-ml-7" />
|
||||
<CarouselNext className="-mr-0 lg:-mr-7" />
|
||||
</Carousel>
|
||||
{/* Judul */}
|
||||
<div className="absolute bottom-5 left-0 right-16 bg-transparent backdrop-blur-md text-white p-4 border-l-2 border-[#bb3523] z-10 group-hover:scale-x-150 origin-left">
|
||||
<h3 className="text-sm font-semibold truncate">{category?.name}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{/* <div className="flex items-center flex-row justify-center">
|
||||
<Button onClick={() => setSeeAllValue(!seeAllValue)} className="bg-white hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]">
|
||||
{seeAllValue ? t("seeLess") : t("seeMore")}
|
||||
</Button>
|
||||
</div> */}
|
||||
<div className="flex items-center flex-row justify-center mt-7">
|
||||
|
||||
{/* Tombol See More / See Less */}
|
||||
{categories?.length > 8 && (
|
||||
<div className="flex items-center flex-row justify-center mt-6">
|
||||
<Button onClick={() => setSeeAllValue(!seeAllValue)} className="bg-white hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]">
|
||||
{seeAllValue ? t("seeLess") : t("seeMore")}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* <div className="flex items-center flex-row justify-center mt-7">
|
||||
<div
|
||||
onClick={() =>
|
||||
router.push(
|
||||
|
|
@ -152,7 +118,7 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
|||
>
|
||||
{t("seeAll")}
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</Reveal>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,47 @@
|
|||
import { getCategoryData, getPublicCategoryData } from "@/service/landing/landing";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
getCategoryData,
|
||||
getPublicCategoryData,
|
||||
} from "@/service/landing/landing";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useParams } from "next/navigation";
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
const ContentCategory = (props: { group?: string }) => {
|
||||
import { useRouter } from "@/i18n/routing";
|
||||
import { Reveal } from "../Reveal";
|
||||
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
|
||||
|
||||
const ContentCategoryKaltara = (props: { group?: string; type: string }) => {
|
||||
const [categories, setCategories] = useState<any>();
|
||||
const t = useTranslations("LandingPage");
|
||||
const params = useParams();
|
||||
const locale = params?.locale;
|
||||
const [selectedTab, setSelectedTab] = useState("image");
|
||||
const poldaName = params?.polda_name;
|
||||
const satkerName = params?.satker_name;
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [seeAllValue, setSeeAllValue] = useState(false);
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
let prefixPath = poldaName
|
||||
? `/polda/${poldaName}`
|
||||
: satkerName
|
||||
? `/satker/${satkerName}`
|
||||
: "/";
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
}, []);
|
||||
const initFetch = async () => {
|
||||
const response = await getPublicCategoryData(
|
||||
props.group == "mabes" ? "" : props.group == "polda" && poldaName && String(poldaName)?.length > 1 ? poldaName : props.group == "satker" && satkerName && String(satkerName)?.length > 1 ? "satker-" + satkerName : "",
|
||||
props.group == "mabes"
|
||||
? ""
|
||||
: props.group == "polda" && poldaName && String(poldaName)?.length > 1
|
||||
? poldaName
|
||||
: props.group == "satker" &&
|
||||
satkerName &&
|
||||
String(satkerName)?.length > 1
|
||||
? "satker-" + satkerName
|
||||
: "",
|
||||
"",
|
||||
locale == "en" ? true : false
|
||||
);
|
||||
|
|
@ -32,6 +49,10 @@ const ContentCategory = (props: { group?: string }) => {
|
|||
setCategories(response?.data?.data?.content);
|
||||
};
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [seeAllValue, setSeeAllValue] = useState(false);
|
||||
const pathname = usePathname();
|
||||
|
||||
const shimmer = (w: number, h: number) => `
|
||||
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
|
|
@ -46,71 +67,88 @@ const ContentCategory = (props: { group?: string }) => {
|
|||
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||
</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 (
|
||||
<div className="mx-auto px-4 lg:px-24 py-10 max-w-screen-2xl ">
|
||||
<div className="px-4 lg:px-24 py-10">
|
||||
<Reveal>
|
||||
<h2 className="text-center text-xl lg:text-2xl font-bold text-[#bb3523] mb-4">
|
||||
<h2 className="text-center text-xl lg:text-3xl font-bold text-[#bb3523] mb-4">
|
||||
{pathname?.split("/")[1] == "in" ? (
|
||||
<>
|
||||
<span className="text-black dark:text-white">{t("category")} </span>
|
||||
<span className="text-black dark:text-white">
|
||||
{t("category")}
|
||||
</span>
|
||||
{t("content")}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-black dark:text-white">{t("content")} </span>
|
||||
<span className="text-black dark:text-white">
|
||||
{t("content")}
|
||||
</span>
|
||||
{t("category")}
|
||||
</>
|
||||
)}
|
||||
</h2>
|
||||
<div className="h-1 w-48 bg-[#bb3523] mx-auto mb-6 rounded"></div>
|
||||
<div className="h-1 w-52 bg-[#bb3523] mx-auto mb-6 rounded"></div>
|
||||
|
||||
<div className="grid my-3 grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{categories?.map((category: any, index: number) =>
|
||||
!seeAllValue ? (
|
||||
index < 4 ? (
|
||||
<Link key={category?.id} href={`all/filter?category=${category?.id}`} className="relative group rounded-md overflow-hidden shadow-md hover:shadow-lg">
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
|
||||
alt="category"
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={category?.thumbnailLink}
|
||||
className="w-full h-48 sm:h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
<div className="absolute bottom-0 rounded-lg left-0 right-0 bg-gray-400 border-l-4 mb-4 border-[#bb3523] text-white p-2">
|
||||
<h3 className="text-sm font-semibold truncate">{category?.name}</h3>
|
||||
<div className="">
|
||||
<Carousel className="w-full max-w-full">
|
||||
<CarouselContent>
|
||||
{categories?.map((category: any) => (
|
||||
<CarouselItem key={category?.id} className="md:basis-1/2 lg:basis-1/3">
|
||||
<div onClick={() => router.push(prefixPath + `all/filter?category=${category?.id}`)} className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block">
|
||||
{/* Gambar */}
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||
shimmer(700, 475)
|
||||
)}`}
|
||||
alt="category"
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={category?.thumbnailLink}
|
||||
className="w-full lg:h-[250px] h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
|
||||
{/* Overlay gelap */}
|
||||
<div className="absolute inset-0 bg-black bg-opacity-25 group-hover:bg-opacity-35 transition-all duration-300 rounded-md"></div>
|
||||
|
||||
{/* Judul */}
|
||||
<div className="absolute bottom-5 left-0 right-16 bg-transparent backdrop-blur-md text-white p-4 border-l-2 border-[#bb3523] z-10 group-hover:scale-x-150 origin-left">
|
||||
<h3 className="text-sm font-semibold truncate">
|
||||
{category?.name}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
) : (
|
||||
<Link key={category?.id} href={`all/filter?category=${category?.id}`} className="relative group rounded-md overflow-hidden shadow-md hover:shadow-lg">
|
||||
<Image
|
||||
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
|
||||
alt="category"
|
||||
width={2560}
|
||||
height={1440}
|
||||
src={category?.thumbnailLink}
|
||||
className="w-full h-48 sm:h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
<div className="absolute bottom-0 left-0 right-0 bg-gray-400 border-l-4 mb-4 border-[#bb3523] rounded-lg text-white p-2">
|
||||
<h3 className="text-sm font-semibold truncate">{category?.name}</h3>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
<CarouselPrevious className="-ml-0 lg:-ml-7" />
|
||||
<CarouselNext className="-mr-0 lg:-mr-7" />
|
||||
</Carousel>
|
||||
</div>
|
||||
<div className="flex items-center flex-row justify-center">
|
||||
{/* <div className="flex items-center flex-row justify-center">
|
||||
<Button onClick={() => setSeeAllValue(!seeAllValue)} className="bg-white hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]">
|
||||
{seeAllValue ? t("seeLess") : t("seeMore")}
|
||||
</Button>
|
||||
</div> */}
|
||||
<div className="flex items-center flex-row justify-center mt-7">
|
||||
<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]"
|
||||
>
|
||||
{t("seeAll")}
|
||||
</div>
|
||||
</div>
|
||||
</Reveal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContentCategory;
|
||||
export default ContentCategoryKaltara;
|
||||
|
|
|
|||
|
|
@ -155,11 +155,11 @@ const Navbar = () => {
|
|||
|
||||
return (
|
||||
<div className="bg-[#f7f7f7] dark:bg-black shadow-md sticky top-0 z-50">
|
||||
<div className="flex items-center justify-between px-4 lg:px-20 gap-3">
|
||||
<div className="flex items-center justify-between px-4 lg:px-20 py-0 gap-3">
|
||||
<div className="flex flex-row gap-8">
|
||||
{/* Logo */}
|
||||
<Link href={prefixPath} className="flex items-center w-[150px] h-[120px]">
|
||||
<Image src="/assets/mediahub-logo.gif" alt="Media Hub Logo" width={200} height={300} className="object-contain" />
|
||||
<Link href={prefixPath} className="flex items-center">
|
||||
<Image src="/assets/mediahub-logo.gif" alt="Media Hub Logo" width={2560} height={1440} className="w-[125px] lg:w-[250px] h-[115px] lg:h-full object-contain" />
|
||||
</Link>
|
||||
|
||||
{/* Nav Menu */}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,11 @@ export async function deleteBlogComments(slug: any) {
|
|||
}
|
||||
|
||||
export async function sendMessage(data: any) {
|
||||
const url = 'inbox';
|
||||
return httpPostInterceptor( url, data );
|
||||
const url = "inbox";
|
||||
return httpPostInterceptor(url, data);
|
||||
}
|
||||
|
||||
export async function enableListCategory() {
|
||||
const url = `media/categories/list/publish?enablePage=1`;
|
||||
return httpPostInterceptor(url);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue