feat:filter date top article dashboar, create magazine category
This commit is contained in:
parent
70ac77dba4
commit
dbb2fbb464
|
|
@ -81,6 +81,9 @@ const createArticleSchema = z.object({
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
category: z.array(categorySchema).nonempty({
|
||||||
|
message: "Kategori harus memiliki setidaknya satu item",
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function NewCreateMagazineForm() {
|
export default function NewCreateMagazineForm() {
|
||||||
|
|
@ -90,6 +93,30 @@ export default function NewCreateMagazineForm() {
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
const [thumbnailImg, setThumbnailImg] = useState<File[]>([]);
|
const [thumbnailImg, setThumbnailImg] = useState<File[]>([]);
|
||||||
|
const [listCategory, setListCategory] = useState<CategoryType[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategory();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchCategory = async () => {
|
||||||
|
const res = await getArticleByCategory();
|
||||||
|
if (res?.data?.data) {
|
||||||
|
setupCategory(res?.data?.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setupCategory = (data: any) => {
|
||||||
|
const temp = [];
|
||||||
|
for (const element of data) {
|
||||||
|
temp.push({
|
||||||
|
id: element.id,
|
||||||
|
label: element.title,
|
||||||
|
value: element.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setListCategory(temp);
|
||||||
|
};
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
onDrop: (acceptedFiles) => {
|
onDrop: (acceptedFiles) => {
|
||||||
|
|
@ -153,6 +180,8 @@ export default function NewCreateMagazineForm() {
|
||||||
typeId: 1,
|
typeId: 1,
|
||||||
slug: values.slug,
|
slug: values.slug,
|
||||||
statusId: 1,
|
statusId: 1,
|
||||||
|
categoryIds: values.category.map((a) => a.id).join(","),
|
||||||
|
|
||||||
// description: htmlToString(removeImgTags(values.description)),
|
// description: htmlToString(removeImgTags(values.description)),
|
||||||
description: values.description,
|
description: values.description,
|
||||||
// rows: values.rows,
|
// rows: values.rows,
|
||||||
|
|
@ -385,6 +414,37 @@ export default function NewCreateMagazineForm() {
|
||||||
{errors?.slug && (
|
{errors?.slug && (
|
||||||
<p className="text-red-400 text-sm mb-3">{errors.slug?.message}</p>
|
<p className="text-red-400 text-sm mb-3">{errors.slug?.message}</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<p className="text-sm mt-3">Kategori</p>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="category"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<ReactSelect
|
||||||
|
className="basic-single text-black z-50"
|
||||||
|
classNames={{
|
||||||
|
control: (state: any) =>
|
||||||
|
"!rounded-lg bg-white !border-1 !border-gray-200 dark:!border-stone-500",
|
||||||
|
}}
|
||||||
|
classNamePrefix="select"
|
||||||
|
onChange={onChange}
|
||||||
|
closeMenuOnSelect={false}
|
||||||
|
components={animatedComponents}
|
||||||
|
isClearable={true}
|
||||||
|
isSearchable={true}
|
||||||
|
isMulti={true}
|
||||||
|
placeholder="Kategori..."
|
||||||
|
name="sub-module"
|
||||||
|
options={listCategory}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors?.category && (
|
||||||
|
<p className="text-red-400 text-sm mb-3">
|
||||||
|
{errors.category?.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
<p className="text-sm mt-3">Thumbnail</p>
|
<p className="text-sm mt-3">Thumbnail</p>
|
||||||
|
|
||||||
{thumbnailImg.length > 0 ? (
|
{thumbnailImg.length > 0 ? (
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,15 @@ export default function DashboardContainer() {
|
||||||
endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
|
endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [topContentDate, setTopContentDate] = useState({
|
||||||
|
startDate: parseDate(
|
||||||
|
convertDateFormatNoTimeV2(
|
||||||
|
new Date(new Date().setDate(new Date().getDate() - 7))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
endDate: parseDate(convertDateFormatNoTimeV2(new Date())),
|
||||||
|
});
|
||||||
|
|
||||||
const [typeDate, setTypeDate] = useState("monthly");
|
const [typeDate, setTypeDate] = useState("monthly");
|
||||||
const [summary, setSummary] = useState<any>();
|
const [summary, setSummary] = useState<any>();
|
||||||
|
|
||||||
|
|
@ -122,7 +131,17 @@ export default function DashboardContainer() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTopPages();
|
fetchTopPages();
|
||||||
}, [topPagespage]);
|
}, [topPagespage, topContentDate]);
|
||||||
|
|
||||||
|
const getDate = (data: any) => {
|
||||||
|
if (data === null) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return `${data.year}-${data.month < 10 ? `0${data.month}` : data.month}-${
|
||||||
|
data.day < 10 ? `0${data.day}` : data.day
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
async function fetchTopPages() {
|
async function fetchTopPages() {
|
||||||
const req = {
|
const req = {
|
||||||
|
|
@ -130,6 +149,8 @@ export default function DashboardContainer() {
|
||||||
page: topPagespage,
|
page: topPagespage,
|
||||||
search: "",
|
search: "",
|
||||||
sort: "desc",
|
sort: "desc",
|
||||||
|
startDate: getDate(topContentDate.startDate),
|
||||||
|
endDate: getDate(topContentDate.endDate),
|
||||||
};
|
};
|
||||||
const res = await getTopArticles(req);
|
const res = await getTopArticles(req);
|
||||||
setTopPages(getTableNumber(10, res.data?.data));
|
setTopPages(getTableNumber(10, res.data?.data));
|
||||||
|
|
@ -139,6 +160,7 @@ export default function DashboardContainer() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchPostCount();
|
fetchPostCount();
|
||||||
}, [postContentDate]);
|
}, [postContentDate]);
|
||||||
|
|
||||||
async function fetchPostCount() {
|
async function fetchPostCount() {
|
||||||
const getDate = (data: any) => {
|
const getDate = (data: any) => {
|
||||||
return `${data.year}-${data.month < 10 ? `0${data.month}` : data.month}-${
|
return `${data.year}-${data.month < 10 ? `0${data.month}` : data.month}-${
|
||||||
|
|
@ -432,14 +454,6 @@ export default function DashboardContainer() {
|
||||||
Mingguan
|
Mingguan
|
||||||
</Button>
|
</Button>
|
||||||
<div className="w-[140px]">
|
<div className="w-[140px]">
|
||||||
{/* <Datepicker
|
|
||||||
value={startDateValue}
|
|
||||||
displayFormat="DD/MM/YYYY"
|
|
||||||
asSingle={true}
|
|
||||||
useRange={false}
|
|
||||||
onChange={(e: any) => setStartDateValue(e)}
|
|
||||||
inputClassName="z-50 w-full text-xs lg:text-sm bg-transparent border-1 border-gray-200 px-2 py-[6px] rounded-sm lg:rounded-lg h-[30px] lg:h-[40px] text-gray-600 dark:text-gray-300"
|
|
||||||
/> */}
|
|
||||||
<Popover
|
<Popover
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||||||
|
|
@ -472,12 +486,64 @@ export default function DashboardContainer() {
|
||||||
<div className="flex flex-col w-full lg:w-[45%] gap-6 shadow-md bg-white dark:bg-[#18181b] rounded-lg p-8 text-xs lg:text-sm">
|
<div className="flex flex-col w-full lg:w-[45%] gap-6 shadow-md bg-white dark:bg-[#18181b] rounded-lg p-8 text-xs lg:text-sm">
|
||||||
<div className="flex justify-between font-semibold">
|
<div className="flex justify-between font-semibold">
|
||||||
<p>Top Pages</p>
|
<p>Top Pages</p>
|
||||||
|
<div className="w-[220px] flex flex-row gap-2 justify-between font-semibold">
|
||||||
|
<Popover
|
||||||
|
placement="bottom"
|
||||||
|
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||||||
|
>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<a className="cursor-pointer">
|
||||||
|
{convertDateFormatNoTime(topContentDate.startDate)}
|
||||||
|
</a>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="bg-transparent">
|
||||||
|
<Calendar
|
||||||
|
value={topContentDate.startDate}
|
||||||
|
onChange={(e) =>
|
||||||
|
setTopContentDate({
|
||||||
|
startDate: e,
|
||||||
|
endDate: topContentDate.endDate,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
maxValue={topContentDate.endDate}
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
-
|
||||||
|
<Popover
|
||||||
|
placement="bottom"
|
||||||
|
classNames={{ content: ["!bg-transparent", "p-0"] }}
|
||||||
|
>
|
||||||
|
<PopoverTrigger>
|
||||||
|
<a className="cursor-pointer ">
|
||||||
|
{convertDateFormatNoTime(topContentDate.endDate)}
|
||||||
|
</a>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent className="bg-transparent">
|
||||||
|
<Calendar
|
||||||
|
value={topContentDate.endDate}
|
||||||
|
onChange={(e) =>
|
||||||
|
setTopContentDate({
|
||||||
|
startDate: topContentDate.startDate,
|
||||||
|
endDate: e,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
minValue={topContentDate.startDate}
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row border-b-1">
|
<div className="flex flex-row border-b-1">
|
||||||
<div className="w-[5%]">No</div>
|
<div className="w-[5%]">No</div>
|
||||||
<div className="w-[85%]">Title</div>
|
<div className="w-[85%]">Title</div>
|
||||||
<div className="w-[10%] text-center">Visits</div>
|
<div className="w-[10%] text-center">Visits</div>
|
||||||
</div>
|
</div>
|
||||||
|
{(!topPages || topPages?.length < 1) && (
|
||||||
|
<div className="flex justify-center items-center">
|
||||||
|
Tidak ada Data
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{topPages?.map((list) => (
|
{topPages?.map((list) => (
|
||||||
<div key={list.id} className="flex flex-row border-b-1">
|
<div key={list.id} className="flex flex-row border-b-1">
|
||||||
<div className="w-[5%]">{list?.no}</div>
|
<div className="w-[5%]">{list?.no}</div>
|
||||||
|
|
@ -485,23 +551,25 @@ export default function DashboardContainer() {
|
||||||
<div className="w-[10%] text-center">{list?.viewCount}</div>
|
<div className="w-[10%] text-center">{list?.viewCount}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div className="my-2 w-full flex justify-center">
|
{topPages?.length > 0 && (
|
||||||
<Pagination
|
<div className="my-2 w-full flex justify-center">
|
||||||
isCompact
|
<Pagination
|
||||||
showControls
|
isCompact
|
||||||
showShadow
|
showControls
|
||||||
color="primary"
|
showShadow
|
||||||
classNames={{
|
color="primary"
|
||||||
base: "bg-transparent",
|
classNames={{
|
||||||
wrapper: "bg-transparent",
|
base: "bg-transparent",
|
||||||
item: "w-fit px-3",
|
wrapper: "bg-transparent",
|
||||||
cursor: "w-fit px-3",
|
item: "w-fit px-3",
|
||||||
}}
|
cursor: "w-fit px-3",
|
||||||
page={topPagespage}
|
}}
|
||||||
total={topPagesTotalPage}
|
page={topPagespage}
|
||||||
onChange={(page) => setTopPagesPage(page)}
|
total={topPagesTotalPage}
|
||||||
/>
|
onChange={(page) => setTopPagesPage(page)}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue