fix:user analytics
This commit is contained in:
parent
34b6586dd2
commit
85778aaf59
|
|
@ -69,98 +69,98 @@ export default function Login() {
|
|||
error("Username & Password Wajib Diisi !");
|
||||
} else {
|
||||
// login dengan otp
|
||||
loading();
|
||||
const response: any = await emailValidation(data);
|
||||
if (response?.error) {
|
||||
console.log("error", response);
|
||||
if (response?.message?.messages[0]?.includes("failed to send mail")) {
|
||||
error("Gagal Mengirim OTP");
|
||||
return false;
|
||||
}
|
||||
// loading();
|
||||
// const response: any = await emailValidation(data);
|
||||
// if (response?.error) {
|
||||
// console.log("error", response);
|
||||
// if (response?.message?.messages[0]?.includes("failed to send mail")) {
|
||||
// error("Gagal Mengirim OTP");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (response?.message?.messages[0]?.includes("username")) {
|
||||
error("Username / Password Tidak Sesuai");
|
||||
return false;
|
||||
}
|
||||
error("Unknown Error");
|
||||
return false;
|
||||
}
|
||||
close();
|
||||
if (response?.data?.messages[0] === "Continue to setup email") {
|
||||
setFirstLogin(true);
|
||||
} else {
|
||||
setNeedOtp(true);
|
||||
}
|
||||
// if (response?.message?.messages[0]?.includes("username")) {
|
||||
// error("Username / Password Tidak Sesuai");
|
||||
// return false;
|
||||
// }
|
||||
// error("Unknown Error");
|
||||
// return false;
|
||||
// }
|
||||
// close();
|
||||
// if (response?.data?.messages[0] === "Continue to setup email") {
|
||||
// setFirstLogin(true);
|
||||
// } else {
|
||||
// setNeedOtp(true);
|
||||
// }
|
||||
|
||||
// login tanpa otp
|
||||
// loading();
|
||||
// const response = await postSignIn(data);
|
||||
// if (response?.error) {
|
||||
// error("Username / Password Tidak Sesuai");
|
||||
// } else {
|
||||
// const profile = await getProfile(response?.data?.data?.access_token);
|
||||
// const dateTime: any = new Date();
|
||||
loading();
|
||||
const response = await postSignIn(data);
|
||||
if (response?.error) {
|
||||
error("Username / Password Tidak Sesuai");
|
||||
} else {
|
||||
const profile = await getProfile(response?.data?.data?.access_token);
|
||||
const dateTime: any = new Date();
|
||||
|
||||
// const newTime: any = dateTime.getTime() + 10 * 60 * 1000;
|
||||
const newTime: any = dateTime.getTime() + 10 * 60 * 1000;
|
||||
|
||||
// Cookies.set("access_token", response?.data?.data?.access_token, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("refresh_token", response?.data?.data?.refresh_token, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("time_refresh", newTime, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("is_first_login", "true", {
|
||||
// secure: true,
|
||||
// sameSite: "strict",
|
||||
// });
|
||||
// const resActivity = await saveActivity(
|
||||
// {
|
||||
// activityTypeId: 1,
|
||||
// url: "https://kontenhumas.com/auth",
|
||||
// userId: profile?.data?.data?.id,
|
||||
// },
|
||||
// accessData?.id_token
|
||||
// );
|
||||
// Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("uie", profile?.data?.data?.id, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("ufne", profile?.data?.data?.fullname, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("ulie", profile?.data?.data?.userLevelGroup, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("username", profile?.data?.data?.username, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("urie", profile?.data?.data?.userRoleId, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("masterPoldaId", profile?.data?.data?.masterPoldaId, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// Cookies.set("ulne", profile?.data?.data?.userLevelId, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// // Cookies.set("urce", profile?.data?.data?.roleCode, {
|
||||
// // expires: 1,
|
||||
// // });
|
||||
// Cookies.set("email", profile?.data?.data?.email, {
|
||||
// expires: 1,
|
||||
// });
|
||||
// router.push("/admin/dashboard");
|
||||
// Cookies.set("status", "login", {
|
||||
// expires: 1,
|
||||
// });
|
||||
Cookies.set("access_token", response?.data?.data?.access_token, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("refresh_token", response?.data?.data?.refresh_token, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("time_refresh", newTime, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("is_first_login", "true", {
|
||||
secure: true,
|
||||
sameSite: "strict",
|
||||
});
|
||||
const resActivity = await saveActivity(
|
||||
{
|
||||
activityTypeId: 1,
|
||||
url: "https://kontenhumas.com/auth",
|
||||
userId: profile?.data?.data?.id,
|
||||
},
|
||||
accessData?.id_token
|
||||
);
|
||||
Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("uie", profile?.data?.data?.id, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("ufne", profile?.data?.data?.fullname, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("ulie", profile?.data?.data?.userLevelGroup, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("username", profile?.data?.data?.username, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("urie", profile?.data?.data?.userRoleId, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("masterPoldaId", profile?.data?.data?.masterPoldaId, {
|
||||
expires: 1,
|
||||
});
|
||||
Cookies.set("ulne", profile?.data?.data?.userLevelId, {
|
||||
expires: 1,
|
||||
});
|
||||
// Cookies.set("urce", profile?.data?.data?.roleCode, {
|
||||
// expires: 1,
|
||||
// });
|
||||
Cookies.set("email", profile?.data?.data?.email, {
|
||||
expires: 1,
|
||||
});
|
||||
router.push("/admin/dashboard");
|
||||
Cookies.set("status", "login", {
|
||||
expires: 1,
|
||||
});
|
||||
|
||||
// close();
|
||||
// }
|
||||
close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -581,11 +581,11 @@ const SidebarMobile: React.FC<SidebarProps> = ({ updateSidebarData }) => {
|
|||
const roles = Cookies.get("ulie");
|
||||
const rolesId = Cookies.get("urie");
|
||||
|
||||
useEffect(() => {
|
||||
if (!token) {
|
||||
onLogout();
|
||||
}
|
||||
}, [token]);
|
||||
// useEffect(() => {
|
||||
// if (!token) {
|
||||
// onLogout();
|
||||
// }
|
||||
// }, [token]);
|
||||
|
||||
const onLogout = () => {
|
||||
Object.keys(Cookies.get()).forEach((cookieName) => {
|
||||
|
|
|
|||
|
|
@ -582,11 +582,11 @@ const Sidebar: React.FC<SidebarProps> = ({ updateSidebarData }) => {
|
|||
const roles = Cookies.get("ulie");
|
||||
const rolesId = Cookies.get("urie");
|
||||
|
||||
useEffect(() => {
|
||||
if (!token) {
|
||||
onLogout();
|
||||
}
|
||||
}, [token]);
|
||||
// useEffect(() => {
|
||||
// if (!token) {
|
||||
// onLogout();
|
||||
// }
|
||||
// }, [token]);
|
||||
|
||||
const onLogout = () => {
|
||||
Object.keys(Cookies.get()).forEach((cookieName) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,246 @@
|
|||
"use client";
|
||||
import { useEffect, useState } from "react";
|
||||
import ReactApexChart from "react-apexcharts";
|
||||
import dummy from "../../../../const/dummy.json";
|
||||
|
||||
function getRangeAcrossMonths(
|
||||
data: any[],
|
||||
startMonth: number,
|
||||
startDay: number,
|
||||
endMonth: number,
|
||||
endDay: number
|
||||
) {
|
||||
const labels: string[] = [];
|
||||
const users: { name: string; data: number[] }[] = [];
|
||||
const sortedData = data.sort((a, b) => a.month - b.month);
|
||||
console.log("sorted,data", sortedData);
|
||||
for (const monthData of sortedData) {
|
||||
const { month, users: u } = monthData;
|
||||
if (month < startMonth || month > endMonth) continue;
|
||||
console.log("uuu", month, startMonth, endMonth, u.length);
|
||||
|
||||
let startIndex = 0;
|
||||
let endIndex = u[0].data.length - 1;
|
||||
|
||||
if (month === startMonth) startIndex = startDay - 1;
|
||||
if (month === endMonth) endIndex = endDay - 1;
|
||||
|
||||
console.log("start,eend", startIndex, endIndex, month);
|
||||
for (let j = 0; j < u.length; j++) {
|
||||
const now = u[j].data;
|
||||
// console.log("u.j", now);
|
||||
const temp = [];
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
temp.push(now[i]);
|
||||
|
||||
if (j == 0) {
|
||||
const label = `${(i + 1).toString().padStart(2, "0")} - ${month
|
||||
.toString()
|
||||
.padStart(2, "0")}`;
|
||||
|
||||
labels.push(label);
|
||||
}
|
||||
}
|
||||
const existing = users.find((item) => item.name === u[j].name);
|
||||
if (existing) {
|
||||
existing.data.push(...temp); // gabungkan data
|
||||
} else {
|
||||
users.push({ name: u[j].name, data: temp }); // tambahkan baru
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("users", users);
|
||||
|
||||
return { users, labels };
|
||||
}
|
||||
|
||||
const ApexMultiLineChart = (props: {
|
||||
type: string;
|
||||
date: string;
|
||||
range: { start: any; end: any };
|
||||
}) => {
|
||||
const { date, type, range } = props;
|
||||
const [datas, setDatas] = useState<any>([]);
|
||||
const [years, setYear] = useState("");
|
||||
|
||||
const [series, setSeries] = useState<any>([]);
|
||||
const [categories, setCategories] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
initFetch();
|
||||
console.log("type", type);
|
||||
}, [date, type, range.start, range.end]);
|
||||
|
||||
const initFetch = async () => {
|
||||
const splitDate = date.split(" ");
|
||||
const splitDateDaily = String(range.start.year);
|
||||
console.log("split", splitDate);
|
||||
console.log("daily", splitDateDaily);
|
||||
let data: any = [];
|
||||
|
||||
if (
|
||||
(type === "monthly" && splitDate[1] === years) ||
|
||||
(type === "daily" && splitDateDaily === years)
|
||||
) {
|
||||
data = datas;
|
||||
} else {
|
||||
// const res = await getStatisticMonthly(
|
||||
// type === "monthly" ? splitDate[1] : splitDateDaily
|
||||
// );
|
||||
// data = res?.data?.data;
|
||||
data = dummy.data;
|
||||
setDatas(data);
|
||||
}
|
||||
|
||||
if (type === "daily") {
|
||||
console.log(
|
||||
"aaa",
|
||||
range.start.month,
|
||||
range.start.day,
|
||||
range.end.month,
|
||||
range.end.day
|
||||
);
|
||||
const mappedData = getRangeAcrossMonths(
|
||||
data,
|
||||
range.start.month,
|
||||
range.start.day,
|
||||
range.end.month,
|
||||
range.end.day
|
||||
);
|
||||
setSeries(mappedData.users);
|
||||
setCategories(mappedData.labels);
|
||||
}
|
||||
|
||||
if (type === "monthly") {
|
||||
console.log("daaa", data);
|
||||
const getDatas = data?.find(
|
||||
(a: any) =>
|
||||
a.month == Number(splitDate[0]) && a.year === Number(splitDate[1])
|
||||
);
|
||||
if (getDatas) {
|
||||
console.log("datanya", getDatas.users);
|
||||
setSeries(getDatas.users);
|
||||
} else {
|
||||
setSeries([]);
|
||||
}
|
||||
}
|
||||
|
||||
setYear(type === "monthly" ? splitDate[1] : splitDateDaily);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div id="chart">
|
||||
<ReactApexChart
|
||||
series={series}
|
||||
options={{
|
||||
chart: {
|
||||
height: 600,
|
||||
type: "line",
|
||||
dropShadow: {
|
||||
enabled: true,
|
||||
color: "#000",
|
||||
top: 18,
|
||||
left: 7,
|
||||
blur: 10,
|
||||
opacity: 0.5,
|
||||
},
|
||||
zoom: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbar: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
colors: [
|
||||
"#1f77b4",
|
||||
"#2ca02c",
|
||||
"#9467bd",
|
||||
"#8c564b",
|
||||
"#e377c2",
|
||||
"#7f7f7f",
|
||||
"#bcbd22",
|
||||
"#17becf",
|
||||
"#aec7e8",
|
||||
"#98df8a",
|
||||
"#c5b0d5",
|
||||
"#c49c94",
|
||||
"#9edae5",
|
||||
"#393b79",
|
||||
"#637939",
|
||||
"#8c6d31",
|
||||
"#843c39",
|
||||
"#7b4173",
|
||||
"#3182bd",
|
||||
"#6baed6",
|
||||
"#9ecae1",
|
||||
"#31a354",
|
||||
"#74c476",
|
||||
"#a1d99b",
|
||||
"#756bb1",
|
||||
"#9e9ac8",
|
||||
"#bcbddc",
|
||||
"#636363",
|
||||
"#969696",
|
||||
"#bdbdbd",
|
||||
"#17becf",
|
||||
"#8da0cb",
|
||||
"#66c2a5",
|
||||
"#a6d854",
|
||||
"#ffd92f",
|
||||
"#b3b3b3",
|
||||
"#80b1d3",
|
||||
"#fdb462",
|
||||
],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
},
|
||||
stroke: {
|
||||
curve: "smooth",
|
||||
},
|
||||
title: {
|
||||
text: "Users",
|
||||
align: "left",
|
||||
},
|
||||
grid: {
|
||||
borderColor: "#e7e7e7",
|
||||
row: {
|
||||
colors: ["#f3f3f3", "transparent"],
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
markers: {
|
||||
size: 0.5,
|
||||
},
|
||||
xaxis: {
|
||||
categories: type == "daily" ? categories : [],
|
||||
|
||||
title: {
|
||||
text: "Days",
|
||||
},
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: "Articles",
|
||||
},
|
||||
min: 0,
|
||||
max: 50,
|
||||
},
|
||||
legend: {
|
||||
position: "right",
|
||||
horizontalAlign: "right",
|
||||
floating: false,
|
||||
offsetY: -25,
|
||||
offsetX: -5,
|
||||
},
|
||||
}}
|
||||
type="line"
|
||||
height={600}
|
||||
/>
|
||||
</div>
|
||||
<div id="html-dist"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApexMultiLineChart;
|
||||
|
|
@ -70,6 +70,7 @@ import { format } from "date-fns";
|
|||
import ApexChartColumnVisitors from "./chart/visitor-chart";
|
||||
import IndonesiaMap from "@/components/ui/maps-charts";
|
||||
import ApexChartDynamic from "./chart/dynamic-bar-char";
|
||||
import ApexMultiLineChart from "./chart/multiline-chart";
|
||||
|
||||
type ArticleData = Article & {
|
||||
no: number;
|
||||
|
|
@ -240,12 +241,29 @@ export default function DashboardContainer() {
|
|||
end: parseDate(convertDateFormatNoTimeV2(today)),
|
||||
});
|
||||
|
||||
const [typeDateUsers, setTypeDateUsers] = useState("daily");
|
||||
const [usersYear, setUsersYear] = useState(today.getFullYear());
|
||||
const [usersSelectedMonth, setUsersSelectedMonth] = useState<Date | null>(
|
||||
today
|
||||
);
|
||||
const [usersDailyDate, setUsersDailyDate] = useState({
|
||||
start: parseDate(
|
||||
convertDateFormatNoTimeV2(
|
||||
new Date(new Date().setDate(new Date().getDate() - 30))
|
||||
)
|
||||
),
|
||||
end: parseDate(convertDateFormatNoTimeV2(today)),
|
||||
});
|
||||
|
||||
const handleMonthClick = (monthIndex: number) => {
|
||||
setSelectedMonth(new Date(year, monthIndex, 1));
|
||||
};
|
||||
|
||||
const handleMonthClickVisitor = (monthIndex: number) => {
|
||||
setVisitorSelectedMonth(new Date(year, monthIndex, 1));
|
||||
setVisitorSelectedMonth(new Date(visitorYear, monthIndex, 1));
|
||||
};
|
||||
const handleMonthClickUsers = (monthIndex: number) => {
|
||||
setUsersSelectedMonth(new Date(usersYear, monthIndex, 1));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -760,8 +778,8 @@ export default function DashboardContainer() {
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full flex flex-col lg:flex-row gap-6 justify-center lg:h-[700px]">
|
||||
<div className="border-1 shadow-sm w-screen rounded-lg lg:w-[50%] p-6 flex flex-col">
|
||||
<div className="w-full flex flex-col gap-6 justify-center">
|
||||
<div className="border-1 shadow-sm w-full rounded-lg p-6 flex flex-col">
|
||||
<div className="flex justify-between mb-3">
|
||||
<div className="font-semibold flex flex-col">
|
||||
Engagement Analytics
|
||||
|
|
@ -899,7 +917,7 @@ export default function DashboardContainer() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-1 shadow-sm w-screen rounded-lg md:w-[50%] p-6 flex flex-col h-[700px]">
|
||||
<div className="border-1 shadow-sm w-full rounded-lg p-6 flex flex-col h-[700px]">
|
||||
<div className="flex justify-between mb-3">
|
||||
<div className="font-semibold flex flex-col">Users Analytics</div>
|
||||
<div className="flex flex-col lg:flex-row gap-2">
|
||||
|
|
@ -907,16 +925,16 @@ export default function DashboardContainer() {
|
|||
className="w-full md:w-[140px] text-xs lg:text-sm h-[30px] lg:h-[40px]"
|
||||
label=""
|
||||
labelPlacement="outside"
|
||||
selectedKeys={[typeDateVisitor]}
|
||||
selectedKeys={[typeDateUsers]}
|
||||
onChange={(e) =>
|
||||
e.target.value !== "" && setTypeDateVisitor(e.target.value)
|
||||
e.target.value !== "" && setTypeDateUsers(e.target.value)
|
||||
}
|
||||
>
|
||||
<SelectItem key="monthly">Bulanan</SelectItem>
|
||||
<SelectItem key="daily">Harian</SelectItem>
|
||||
</Select>
|
||||
|
||||
{typeDateVisitor === "monthly" ? (
|
||||
{typeDateUsers === "monthly" ? (
|
||||
<Popover
|
||||
placement="bottom"
|
||||
showArrow={true}
|
||||
|
|
@ -925,8 +943,8 @@ export default function DashboardContainer() {
|
|||
<PopoverTrigger>
|
||||
<Button className="w-[140px] text-xs lg:text-sm h-[30px] lg:h-[40px] rounded-sm lg:rounded-lg">
|
||||
{" "}
|
||||
{visitorSelectedMonth
|
||||
? format(visitorSelectedMonth, "MMMM yyyy")
|
||||
{usersSelectedMonth
|
||||
? format(usersSelectedMonth, "MMMM yyyy")
|
||||
: "Pilih Bulan"}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
|
@ -934,7 +952,7 @@ export default function DashboardContainer() {
|
|||
<div className="flex items-center justify-between mb-2 px-1 w-full">
|
||||
<button
|
||||
className="text-gray-500 hover:text-black"
|
||||
onClick={() => setVisitorYear((prev) => prev - 1)}
|
||||
onClick={() => setUsersYear((prev) => prev - 1)}
|
||||
>
|
||||
<ChevronLeftIcon />
|
||||
</button>
|
||||
|
|
@ -943,7 +961,7 @@ export default function DashboardContainer() {
|
|||
</span>
|
||||
<button
|
||||
className="text-gray-500 hover:text-black"
|
||||
onClick={() => setVisitorYear((prev) => prev + 1)}
|
||||
onClick={() => setUsersYear((prev) => prev + 1)}
|
||||
>
|
||||
<ChevronRightIcon />
|
||||
</button>
|
||||
|
|
@ -953,11 +971,11 @@ export default function DashboardContainer() {
|
|||
{months.map((month, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => handleMonthClickVisitor(idx)}
|
||||
onClick={() => handleMonthClickUsers(idx)}
|
||||
className={`py-1 rounded-md text-sm transition-colors ${
|
||||
visitorSelectedMonth &&
|
||||
visitorSelectedMonth.getMonth() === idx &&
|
||||
visitorSelectedMonth.getFullYear() === year
|
||||
usersSelectedMonth &&
|
||||
usersSelectedMonth.getMonth() === idx &&
|
||||
usersSelectedMonth.getFullYear() === year
|
||||
? "bg-blue-500 text-white"
|
||||
: "hover:bg-gray-200 text-gray-700"
|
||||
}`}
|
||||
|
|
@ -972,8 +990,8 @@ export default function DashboardContainer() {
|
|||
<div className="w-[220px]">
|
||||
<DateRangePicker
|
||||
className="h-[40px]"
|
||||
value={visitorDailyDate}
|
||||
onChange={(e) => e !== null && setVisitorDailyDate(e)}
|
||||
value={usersDailyDate}
|
||||
onChange={(e) => e !== null && setUsersDailyDate(e)}
|
||||
label=""
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -982,27 +1000,18 @@ export default function DashboardContainer() {
|
|||
</div>
|
||||
<div className="flex flex-row w-full h-full">
|
||||
<div className="w-full h-[30vh] lg:h-full text-black">
|
||||
<ApexChartDynamic
|
||||
key={`${
|
||||
convertDateFormatNoTimeV2(
|
||||
String(visitorSelectedMonth)
|
||||
).split("-")[1]
|
||||
} ${
|
||||
convertDateFormatNoTimeV2(
|
||||
String(visitorSelectedMonth)
|
||||
).split("-")[0]
|
||||
}-${typeDateVisitor}-${visitorDailyDate}`}
|
||||
type={typeDateVisitor}
|
||||
<ApexMultiLineChart
|
||||
type={typeDateUsers}
|
||||
date={`${
|
||||
convertDateFormatNoTimeV2(
|
||||
String(visitorSelectedMonth)
|
||||
).split("-")[1]
|
||||
convertDateFormatNoTimeV2(String(usersSelectedMonth)).split(
|
||||
"-"
|
||||
)[1]
|
||||
} ${
|
||||
convertDateFormatNoTimeV2(
|
||||
String(visitorSelectedMonth)
|
||||
).split("-")[0]
|
||||
convertDateFormatNoTimeV2(String(usersSelectedMonth)).split(
|
||||
"-"
|
||||
)[0]
|
||||
}`}
|
||||
range={visitorDailyDate}
|
||||
range={usersDailyDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
164
const/dummy.json
164
const/dummy.json
|
|
@ -1,46 +1,148 @@
|
|||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"year": 2024,
|
||||
"month": 11,
|
||||
"suggestions": [
|
||||
14, 32, 10, 21, 15, 18, 24, 30, 12, 25, 19, 28, 14, 17, 22, 31, 27, 13,
|
||||
20, 24, 29, 18, 21, 26, 23, 14, 19, 17, 28, 22
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"year": 2024,
|
||||
"month": 12,
|
||||
"suggestions": [
|
||||
15, 23, 19, 14, 18, 20, 22, 17, 21, 19, 23, 16, 25, 20, 18, 19, 22, 24,
|
||||
15, 18, 21, 26, 28, 23, 17, 20, 19, 22, 22, 42, 32
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"year": 2025,
|
||||
"month": 1,
|
||||
"suggestions": [
|
||||
14, 32, 10, 21, 15, 18, 24, 30, 12, 25, 19, 28, 14, 17, 22, 31, 27, 13,
|
||||
20, 24, 29, 18, 21, 26, 23, 14, 19, 17, 28, 22, 21
|
||||
"month": 4,
|
||||
"users": [
|
||||
{
|
||||
"name": "Polda Aceh",
|
||||
"data": [
|
||||
12, 7, 5, 19, 3, 8, 15, 4, 9, 6, 14, 11, 13, 10, 2, 18, 7, 5, 8, 17,
|
||||
4, 6, 14, 15, 3, 10, 12, 9, 6, 13
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Sumatera Utara",
|
||||
"data": [
|
||||
10, 4, 6, 7, 9, 8, 14, 13, 5, 12, 11, 3, 17, 16, 7, 9, 10, 8, 5, 14,
|
||||
11, 4, 6, 9, 15, 13, 3, 7, 10, 12
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Sumatera Barat",
|
||||
"data": [
|
||||
7, 6, 3, 8, 12, 4, 6, 10, 11, 14, 13, 5, 9, 10, 6, 7, 8, 13, 15, 6,
|
||||
7, 5, 8, 14, 11, 13, 4, 6, 12, 10
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Metro Jaya",
|
||||
"data": [
|
||||
12, 7, 5, 19, 3, 8, 15, 4, 9, 6, 14, 11, 13, 10, 2, 18, 7, 5, 8, 17,
|
||||
4, 6, 9, 6, 13, 5, 14, 15, 3, 10
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Jabar",
|
||||
"data": [
|
||||
10, 4, 6, 17, 16, 7, 9, 10, 8, 5, 14, 11, 4, 6, 9, 15, 13, 3, 7, 10,
|
||||
12, 9, 8, 14, 13, 21, 5, 12, 11
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Jateng",
|
||||
"data": [
|
||||
7, 6, 3, 13, 5, 9, 10, 6, 7, 8, 13, 15, 6, 7, 5, 8, 14, 11, 13, 4,
|
||||
4, 6, 10, 11, 14, 2, 6, 12, 10, 8
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"year": 2025,
|
||||
"month": 2,
|
||||
"suggestions": [
|
||||
15, 23, 19, 14, 18, 20, 22, 17, 21, 19, 23, 16, 25, 20, 18, 19, 22, 24,
|
||||
15, 18, 21, 26, 28, 23, 17, 20, 19, 22
|
||||
"month": 5,
|
||||
"users": [
|
||||
{
|
||||
"name": "Polda Aceh",
|
||||
"data": [
|
||||
12, 7, 5, 19, 3, 8, 15, 4, 9, 6, 14, 11, 13, 10, 2, 18, 7, 5, 8, 17,
|
||||
4, 6, 14, 15, 3, 10, 12, 9, 6, 13, 5
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Sumatera Utara",
|
||||
"data": [
|
||||
10, 4, 6, 7, 5, 12, 11, 3, 17, 16, 7, 9, 10, 8, 5, 14, 11, 4, 6, 9,
|
||||
15, 13, 3, 7, 10, 12, 9, 8, 14, 13, 4
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Sumatera Barat",
|
||||
"data": [
|
||||
7, 6, 3, 13, 5, 9, 10, 6, 7, 8, 13, 15, 6, 7, 5, 8, 14, 11, 13, 4,
|
||||
6, 12, 10, 8, 12, 4, 6, 10, 11, 14, 2
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Metro Jaya",
|
||||
"data": [
|
||||
12, 7, 5, 19, 3, 8, 15, 4, 9, 6, 14, 11, 13, 10, 2, 18, 7, 5, 8, 17,
|
||||
4, 6, 9, 6, 13, 5, 14, 15, 3, 10, 12
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Jabar",
|
||||
"data": [
|
||||
10, 4, 6, 17, 16, 7, 9, 10, 8, 5, 14, 11, 4, 6, 9, 15, 13, 3, 7, 10,
|
||||
12, 9, 8, 14, 13, 2, 5, 12, 11, 3, 2
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Jateng",
|
||||
"data": [
|
||||
7, 6, 3, 13, 5, 9, 10, 6, 7, 8, 13, 15, 6, 7, 5, 8, 14, 11, 13, 4,
|
||||
4, 6, 10, 11, 14, 2, 6, 12, 10, 8, 12
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"year": 2025,
|
||||
"month": 3,
|
||||
"suggestions": [14, 32, 10, 21, 15, 18]
|
||||
"month": 6,
|
||||
"users": [
|
||||
{
|
||||
"name": "Polda Aceh",
|
||||
"data": [
|
||||
12, 7, 5, 19, 3, 8, 15, 4, 9, 6, 14, 11, 13, 10, 2, 18, 7, 5, 8, 17,
|
||||
4, 6, 14, 15, 3, 10, 12, 9, 6, 13, 5
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Sumatera Utara",
|
||||
"data": [
|
||||
10, 4, 6, 7, 5, 12, 11, 3, 17, 16, 7, 9, 10, 8, 5, 14, 11, 4, 6, 9,
|
||||
15, 13, 3, 7, 10, 12, 9, 8, 14, 13, 4
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Sumatera Barat",
|
||||
"data": [
|
||||
7, 6, 3, 13, 5, 9, 10, 6, 7, 8, 13, 15, 6, 7, 5, 8, 14, 11, 13, 4,
|
||||
6, 12, 10, 8, 12, 4, 6, 10, 11, 14, 2
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Metro Jaya",
|
||||
"data": [
|
||||
12, 7, 5, 19, 3, 8, 15, 4, 9, 6, 14, 11, 13, 10, 2, 18, 7, 5, 8, 17,
|
||||
4, 6, 9, 6, 13, 5, 14, 15, 3, 10, 12
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Jabar",
|
||||
"data": [
|
||||
10, 4, 6, 17, 16, 7, 9, 10, 8, 5, 14, 11, 4, 6, 9, 15, 13, 3, 7, 10,
|
||||
12, 9, 8, 14, 13, 20, 5, 12, 11, 3
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Polda Jateng",
|
||||
"data": [
|
||||
7, 6, 3, 13, 5, 9, 10, 6, 7, 8, 13, 15, 6, 7, 5, 8, 14, 11, 13, 4,
|
||||
4, 6, 10, 11, 14, 2, 6, 12, 10, 8, 12
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue