fix landing banner article

This commit is contained in:
Rama Priyanto 2025-03-17 22:45:12 +07:00
parent fccb7d60f1
commit a01825a40a
8 changed files with 165 additions and 14059 deletions

View File

@ -45,6 +45,7 @@ export default function HeaderNews() {
search: "", search: "",
limit: "10", limit: "10",
sort: "desc", sort: "desc",
isPublish: true,
}; };
const response = await getListArticle(req); const response = await getListArticle(req);
setArticle(response?.data?.data); setArticle(response?.data?.data);
@ -57,6 +58,7 @@ export default function HeaderNews() {
limit: "10", limit: "10",
sortBy: "view_count", sortBy: "view_count",
sort: "desc", sort: "desc",
category: "586",
isPublish: true, isPublish: true,
}; };
const response = await getListArticle(req); const response = await getListArticle(req);

View File

@ -207,6 +207,15 @@ export default function BannerHumasNew() {
</Accordion> </Accordion>
); );
}; };
const [hasMounted, setHasMounted] = useState(false);
useEffect(() => {
setHasMounted(true);
}, []);
// Render
if (!hasMounted) return null;
return ( return (
<div className="h-fit relative text-white overflow-hidden"> <div className="h-fit relative text-white overflow-hidden">
<div <div

View File

@ -3,6 +3,7 @@ import React, { Component, useEffect, useState } from "react";
import ReactApexChart from "react-apexcharts"; import ReactApexChart from "react-apexcharts";
import dummyData from "../../../../const/dummy.json"; import dummyData from "../../../../const/dummy.json";
import { getStatisticMonthly } from "@/service/article"; import { getStatisticMonthly } from "@/service/article";
import { get } from "http";
type WeekData = { type WeekData = {
week: number; week: number;
@ -43,8 +44,12 @@ function processMonthlyData(count: number[]): {
}; };
} }
const SuggestionsChart = (props: { type: string; date: string }) => { const SuggestionsChart = (props: {
const { date, type } = props; type: string;
date: string;
totals: (data: number) => void;
}) => {
const { date, type, totals } = props;
const [categories, setCategories] = useState<string[]>([]); const [categories, setCategories] = useState<string[]>([]);
const [seriesSuggestions, setSeriesSuggestions] = useState<number[]>([]); const [seriesSuggestions, setSeriesSuggestions] = useState<number[]>([]);
@ -69,15 +74,17 @@ const SuggestionsChart = (props: { type: string; date: string }) => {
]; ];
const category = []; const category = [];
const temp = []; const temp = [];
let totalData = 0;
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const total = data[i].suggestions.reduce( const total = data[i].suggestions.reduce(
(sum: number, list: number) => sum + list, (sum: number, list: number) => sum + list,
0 0
); );
temp.push(total); temp.push(total);
totalData += total;
category.push(months[data[i].month - 1]); category.push(months[data[i].month - 1]);
} }
return { categories: category, series: temp }; return { categories: category, series: temp, total: totalData };
} }
const initFetch = async () => { const initFetch = async () => {
@ -86,16 +93,17 @@ const SuggestionsChart = (props: { type: string; date: string }) => {
// const data = res?.data?.data; // const data = res?.data?.data;
const data = dummyData.data; const data = dummyData.data;
if (type === "monthly") { if (type === "monthly") {
const getDatas = data?.filter( const getDatas = data?.filter((a) => a.year === Number(splitDate[1]));
(a: any) => a.year === Number(splitDate[1]) console.log("teemp,tota", getDatas);
);
if (getDatas) { if (getDatas) {
const temp = processYearlyData(getDatas); const temp = processYearlyData(getDatas);
console.log("temp", temp);
setSeriesSuggestions(temp.series); setSeriesSuggestions(temp.series);
setCategories(temp.categories); setCategories(temp.categories);
totals(temp.total);
} else { } else {
setSeriesSuggestions([]); setSeriesSuggestions([]);
totals(0);
} }
} else { } else {
const getDatas = data?.find( const getDatas = data?.find(
@ -104,24 +112,25 @@ const SuggestionsChart = (props: { type: string; date: string }) => {
); );
if (getDatas) { if (getDatas) {
const temp = processMonthlyData(getDatas?.suggestions); const temp = processMonthlyData(getDatas?.suggestions);
const sum = getDatas.suggestions.reduce((acc, curr) => acc + curr, 0);
totals(sum);
if (type == "weekly") { if (type == "weekly") {
setSeriesSuggestions( setSeriesSuggestions(
temp.weeks.map((list) => { temp.weeks.map((list) => {
return list.total; return list.total;
}) })
); );
} else {
setSeriesSuggestions(getDatas.suggestions);
}
if (type === "weekly") {
const category = []; const category = [];
for (let i = 1; i <= temp.weeks.length; i++) { for (let i = 1; i <= temp.weeks.length; i++) {
category.push(`Minggu ke-${i}`); category.push(`Minggu ke-${i}`);
} }
setCategories(category); setCategories(category);
} else {
setSeriesSuggestions(getDatas.suggestions);
} }
} else { } else {
setSeriesSuggestions([]); setSeriesSuggestions([]);
totals(0);
} }
} }
}; };

View File

@ -20,16 +20,25 @@ import { useEffect, useRef, useState } from "react";
import { getListArticle } from "@/service/article"; import { getListArticle } from "@/service/article";
import { formatMonthString, htmlToString, textEllipsis } from "@/utils/global"; import { formatMonthString, htmlToString, textEllipsis } from "@/utils/global";
import Image from "next/image"; import Image from "next/image";
import { useParams } from "next/navigation"; import {
useParams,
usePathname,
useRouter,
useSearchParams,
} from "next/navigation";
export default function ListNews() { export default function ListNews() {
const [article, setArticle] = useState<any>([]); const [article, setArticle] = useState<any>([]);
const [search, setSearch] = useState("");
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const router = useRouter();
const pathname = usePathname();
const [totalPage, setTotalPage] = useState(1); const [totalPage, setTotalPage] = useState(1);
const topRef = useRef<HTMLDivElement>(null); const topRef = useRef<HTMLDivElement>(null);
const params = useParams(); const params = useParams();
const category = params?.name; const category = params?.name;
const searchParams = useSearchParams();
const search = searchParams.get("search");
const [searchValue, setSearchValue] = useState(search || "");
useEffect(() => { useEffect(() => {
getArticle(); getArticle();
@ -41,9 +50,10 @@ export default function ListNews() {
const req = { const req = {
page: page, page: page,
search: search, search: searchValue || "",
limit: "9", limit: "9",
category: String(category), category: String(category),
isPublish: true,
}; };
const response = await getListArticle(req); const response = await getListArticle(req);
setArticle(response?.data?.data); setArticle(response?.data?.data);
@ -52,7 +62,7 @@ export default function ListNews() {
} }
return ( return (
<div className="bg-white" ref={topRef}> <div className="bg-white border-b-1" ref={topRef}>
<div className="text-black py-5 px-3 lg:w-[75vw] mx-auto bg-white"> <div className="text-black py-5 px-3 lg:w-[75vw] mx-auto bg-white">
<div className="flex flex-row gap-4"> <div className="flex flex-row gap-4">
<Link href="/" className="text-black font-semibold"> <Link href="/" className="text-black font-semibold">
@ -69,13 +79,22 @@ export default function ListNews() {
inputWrapper: "bg-white hover:!bg-gray-100 border-1", inputWrapper: "bg-white hover:!bg-gray-100 border-1",
input: "text-sm !text-black", input: "text-sm !text-black",
}} }}
onKeyDown={(event) => {
if (event.key === "Enter") {
router.push(pathname + `?search=${searchValue}`);
getArticle();
}
}}
labelPlacement="outside" labelPlacement="outside"
placeholder="Search..." placeholder="Search..."
value={search} value={searchValue || ""}
onValueChange={setSearch} onValueChange={setSearchValue}
endContent={ endContent={
<Button <Button
onPress={getArticle} onPress={() => {
router.push(pathname + `?search=${searchValue}`);
getArticle();
}}
size="sm" size="sm"
className="bg-red-500 font-semibold" className="bg-red-500 font-semibold"
> >

View File

@ -100,6 +100,7 @@ export default function SuggestionsTable() {
const [search, setSearch] = useState(""); const [search, setSearch] = useState("");
const [isReply, setIsReply] = useState(false); const [isReply, setIsReply] = useState(false);
const [replyValue, setReplyValue] = useState(""); const [replyValue, setReplyValue] = useState("");
const [totalData, setTotalData] = useState(0);
const formOptions = { const formOptions = {
resolver: zodResolver(createArticleSchema), resolver: zodResolver(createArticleSchema),
@ -302,7 +303,7 @@ export default function SuggestionsTable() {
return ( return (
<> <>
<div className="flex flex-row gap-2"> <div className="flex flex-row gap-2 items-center">
<Button <Button
color="primary" color="primary"
variant={typeDate === "monthly" ? "solid" : "bordered"} variant={typeDate === "monthly" ? "solid" : "bordered"}
@ -342,18 +343,22 @@ export default function SuggestionsTable() {
</PopoverContent> </PopoverContent>
</Popover> </Popover>
</div> </div>
<p className="font-semibold">
Total : <span className="font-bold">{totalData}</span>
</p>
</div> </div>
<div className="flex flex-row w-full h-full"> <div className="flex flex-row w-full h-full">
<div className="w-full h-[30vh] lg:h-[300px] text-black"> <div className="w-full h-[30vh] lg:h-[300px] text-black">
<SuggestionsChart <SuggestionsChart
type={typeDate} type={typeDate}
date={`${startDateValue.month} ${startDateValue.year}`} date={`${startDateValue.month} ${startDateValue.year}`}
totals={(data) => setTotalData(data)}
/> />
</div> </div>
</div> </div>
<div className="py-3"> <div className="py-3">
<div className="flex flex-col items-start rounded-2xl gap-3"> <div className="flex flex-col items-start rounded-2xl gap-3">
<div className="flex flex-col md:flex-row gap-3 w-full"> <div className="flex flex-col md:flex-row gap-3 w-full lg:items-end">
<div className="flex flex-col gap-1 w-full lg:w-1/3"> <div className="flex flex-col gap-1 w-full lg:w-1/3">
<p className="font-semibold text-sm">Pencarian</p> <p className="font-semibold text-sm">Pencarian</p>
<Input <Input
@ -394,6 +399,9 @@ export default function SuggestionsTable() {
</SelectItem> </SelectItem>
</Select> </Select>
</div> </div>
<Button color="primary" className="text-white">
Export
</Button>
</div> </div>
<Table <Table
aria-label="micro issue table" aria-label="micro issue table"

14132
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -67,6 +67,7 @@
"tailwind-variants": "^0.1.18", "tailwind-variants": "^0.1.18",
"tailwindcss": "3.3.5", "tailwindcss": "3.3.5",
"typescript": "5.0.4", "typescript": "5.0.4",
"xlsx": "^0.18.5",
"zod": "^3.23.8", "zod": "^3.23.8",
"zustand": "^5.0.1" "zustand": "^5.0.1"
} }

View File

@ -28,7 +28,7 @@ export async function getListArticle(props: PaginationRequest) {
isPublish === undefined ? "" : isPublish isPublish === undefined ? "" : isPublish
}&title=${search}&startDate=${startDate || ""}&endDate=${ }&title=${search}&startDate=${startDate || ""}&endDate=${
endDate || "" endDate || ""
}&category=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${ }&categoryId=${category || ""}&sortBy=${sortBy || "created_at"}&sort=${
sort || "asc" sort || "asc"
}`, }`,
headers headers
@ -93,7 +93,7 @@ export async function getArticleByCategory() {
"content-type": "application/json", "content-type": "application/json",
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
}; };
return await httpGet(`/article-categories?limit=200`, headers); return await httpGet(`/article-categories?limit=1000`, headers);
} }
export async function getCategoryPagination(data: any) { export async function getCategoryPagination(data: any) {
const headers = { const headers = {