diff --git a/components/form/login.tsx b/components/form/login.tsx index d4d792f..d117ff5 100644 --- a/components/form/login.tsx +++ b/components/form/login.tsx @@ -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(); + } } }; diff --git a/components/main/dashboard/chart/column-chart.tsx b/components/main/dashboard/chart/column-chart.tsx index 75b0578..1ffbfcc 100644 --- a/components/main/dashboard/chart/column-chart.tsx +++ b/components/main/dashboard/chart/column-chart.tsx @@ -56,7 +56,6 @@ function getRangeAcrossMonths( const labels: string[] = []; const sortedData = data.sort((a, b) => a.month - b.month); - console.log("sorted data", sortedData); for (const monthData of sortedData) { const { month, view: v, comment: c, share: s } = monthData; @@ -75,7 +74,7 @@ function getRangeAcrossMonths( const label = `${(i + 1).toString().padStart(2, "0")} - ${month .toString() - .padStart(2, "0")} `; + .padStart(2, "0")}`; labels.push(label); } } @@ -106,16 +105,11 @@ const ApexChartColumn = (props: { const splitDate = date.split(" "); const splitDateDaily = String(range.start.year); let data = []; - console.log( - "aaawwww", - type === "monthly" && splitDate[1] === years, - type === "daily" && splitDateDaily === years - ); + if ( (type === "monthly" && splitDate[1] === years) || (type === "daily" && splitDateDaily === years) ) { - console.log("if", datas); data = datas; } else { const res = await getStatisticMonthly( @@ -124,7 +118,6 @@ const ApexChartColumn = (props: { data = res?.data?.data; setDatas(data); } - console.log("datas", data); const getDatas = data?.find( (a: any) => a.month == Number(splitDate[0]) && a.year === Number(splitDate[1]) diff --git a/components/main/dashboard/chart/dynamic-bar-char.tsx b/components/main/dashboard/chart/dynamic-bar-char.tsx new file mode 100644 index 0000000..aded7ee --- /dev/null +++ b/components/main/dashboard/chart/dynamic-bar-char.tsx @@ -0,0 +1,369 @@ +import React, { useState, useCallback, useEffect, useRef } from "react"; +import ReactApexChart from "react-apexcharts"; +import ApexCharts from "apexcharts"; +import { init } from "next/dist/compiled/webpack/webpack"; + +const wilayah = ["sumut", "bali", "jateng", "jabar", "metro", "papua", "riau"]; + +type TypeItem = { + year: number; + month: number; + user: { + list: { name: string; count: number }[]; + }[]; +}; + +interface MappedData { + result: { x: string; y: number }[] | []; + details: { name: string; count: number }[][]; +} + +const generateDummyData = () => { + const getDaysInMonth = (year: number, month: number) => { + return new Date(year, month, 0).getDate(); + }; + + const dummy = []; + + for (let month = 1; month <= 7; month++) { + const userData = []; + const daysInMonth = getDaysInMonth(2025, month); + + for (let day = 1; day <= daysInMonth; day++) { + // Buat 2-4 wilayah acak per hari + const regionCount = Math.floor(Math.random() * 3) + 2; + const usedRegions = wilayah + .sort(() => 0.5 - Math.random()) + .slice(0, regionCount); + + const list = usedRegions.map((name) => ({ + name, + count: Math.floor(Math.random() * 10) + 1, + })); + + userData.push({ list }); + } + + dummy.push({ + year: 2025, + month, + user: userData, + }); + } + + return dummy; +}; + +const dummy = generateDummyData(); + +const colors = ["#008FFB"]; + +export const makeDataByMonth = ( + data: TypeItem[], + month: number +): MappedData => { + const result: { x: string; y: number }[] = []; + const details: { name: string; count: number }[][] = []; + + const filtered = data.find((entry) => entry.month === month); + + if (!filtered) return { result: [], details: [] }; + + filtered.user.forEach((u, idx) => { + const total = u.list.reduce((sum, item) => sum + item.count, 0); + details.push(u.list); + console.log("u.list", u.list); + result.push({ + x: (idx + 1).toString(), + y: total, + }); + }); + + return { result, details }; +}; + +export const makeDataByRange = ( + data: TypeItem[], + startMonth: number, + startDay: number, + endMonth: number, + endDay: number +) => { + const user: number[] = []; + const labels: string[] = []; + const details = []; + const result: { x: string; y: number }[] = []; + const sortedData = data.sort((a, b) => a.month - b.month); + for (const monthData of sortedData) { + const { month, user: u } = monthData; + + if (month < startMonth || month > endMonth) continue; + + let startIndex = 0; + let endIndex = u.length - 1; + + if (month === startMonth) startIndex = startDay - 1; + if (month === endMonth) endIndex = endDay - 1; + + for (let i = startIndex; i <= endIndex; i++) { + const userEntry = u[i]; + + if (!userEntry) continue; + + const total = userEntry.list.reduce((sum, item) => sum + item.count, 0); + user.push(total); + details.push(userEntry.list); + const label = `${(i + 1).toString().padStart(2, "0")} - ${month + .toString() + .padStart(2, "0")}`; + labels.push(label); + } + } + + for (let i = 0; i < user.length; i++) { + result.push({ x: labels[i], y: user[i] }); + } + + return { result, details }; +}; + +const ApexChartDynamic = (props: { + type: string; + date: string; + range: { start: any; end: any }; +}) => { + const { date, type, range } = props; + const [state, setState] = useState<{ + series: ApexAxisChartSeries; + options: ApexCharts.ApexOptions; + seriesQuarter: ApexAxisChartSeries; + }>({ + series: [{ data: [] }], + options: { + chart: { + id: "barYear", + height: 600, + width: "100%", + type: "bar", + events: { + dataPointSelection: function (e, chart, opts) { + const quarterChartEl = document.querySelector("#chart-quarter"); + const yearChartEl = document.querySelector("#chart-year"); + + if (!quarterChartEl || !yearChartEl) return; + + if (opts.selectedDataPoints[0].length === 1) { + if (quarterChartEl.classList.contains("active")) { + updateQuarterChart(chart, "barQuarter"); + } else { + yearChartEl.classList.add("chart-quarter-activated"); + quarterChartEl.classList.add("active"); + updateQuarterChart(chart, "barQuarter"); + } + } else { + updateQuarterChart(chart, "barQuarter"); + } + + if (opts.selectedDataPoints[0].length === 0) { + yearChartEl.classList.remove("chart-quarter-activated"); + quarterChartEl.classList.remove("active"); + } + }, + updated: function (chart) { + updateQuarterChart(chart, "barQuarter"); + }, + }, + }, + plotOptions: { + bar: { + distributed: true, + horizontal: true, + barHeight: "100%", + dataLabels: { + position: "bottom", + }, + }, + }, + dataLabels: { + enabled: true, + textAnchor: "start", + style: { + colors: ["#fff"], + }, + formatter: function (_val, opt) { + return opt.w.globals.labels[opt.dataPointIndex]; + }, + offsetX: 0, + dropShadow: { + enabled: true, + }, + }, + colors: colors, + states: { + normal: { + filter: { + type: "desaturate", + }, + }, + active: { + allowMultipleDataPointsSelection: false, + filter: { + type: "darken", + value: 1, + }, + }, + }, + legend: { + show: false, + }, + tooltip: { + x: { show: false }, + y: { + title: { + formatter: ((_seriesName: string, opts: any) => + opts.w.globals.labels[opts.dataPointIndex]) as ( + seriesName: string + ) => string, + }, + }, + }, + + yaxis: { + labels: { + show: false, + }, + }, + }, + seriesQuarter: [{ data: [] }], + }); + + const [years, setYear] = useState(""); + const [datas, setDatas] = useState([]); + const [details, setDetails] = useState<{ name: string; count: number }[][]>( + [] + ); + const detailsRef = useRef(details); + + useEffect(() => { + detailsRef.current = details; + }, [details]); + + useEffect(() => { + initFetch(); + }, [date, range.start, range.end, type]); + + const initFetch = async () => { + const splitDate = date.split(" "); + const splitDateDaily = String(range.start.year); + const currentYear = type === "monthly" ? splitDate[1] : splitDateDaily; + + let data = []; + + if (currentYear === years) { + console.log("if", datas); + data = datas; + } else { + // const res = await getStatisticMonthly( + // type === "monthly" ? splitDate[1] : splitDateDaily + // ); + // data = res?.data?.data; + data = dummy; + console.log("dataaa", data); + setDatas(data); + setYear(currentYear); + } + // console.log("datas", data); + if (data) { + if (type == "monthly") { + const mappedData: MappedData = makeDataByMonth( + data, + Number(splitDate[0]) + ); + console.log("mapped month", mappedData); + setDetails(mappedData.details); + setState((prev) => ({ + ...prev, + series: [{ data: mappedData.result }], + })); + } + + if (type == "daily") { + const mappedData = makeDataByRange( + data, + range.start.month, + range.start.day, + range.end.month, + range.end.day + ); + console.log("mmapped,", mappedData.details); + setDetails(mappedData.details); + setState((prev) => ({ + ...prev, + series: [{ data: mappedData.result }], + })); + } + } else { + setState((prev) => ({ + ...prev, + series: [{ data: [] }], + })); + } + }; + + const updateQuarterChart = useCallback( + (chart: any, id: string) => { + const selectedIndex = chart?.w?.config?.series[0]?.data?.findIndex( + (d: any, i: number) => { + return chart.w.globals.selectedDataPoints[0]?.includes(i); + } + ); + + if (selectedIndex !== -1) { + const counts = detailsRef.current[selectedIndex]; + console.log("countres", counts, detailsRef); + + const quarterData = [ + { + name: `${selectedIndex + 1}`, + data: counts, + }, + ]; + ApexCharts.exec(id, "updateSeries", quarterData); + + setState((prev: any) => ({ + ...prev, + seriesQuarter: quarterData, + })); + } + }, + [detailsRef] + ); + + return ( +
+
+
+ +
+ +
+
+ {state.seriesQuarter[0].data.map((list: any, index) => ( +
+

{list?.name} :

+

{list?.count}

+
+ ))} +
+
+
+
+ ); +}; + +export default ApexChartDynamic; diff --git a/components/main/dashboard/chart/visitor-chart.tsx b/components/main/dashboard/chart/visitor-chart.tsx index 58e57af..9027ec2 100644 --- a/components/main/dashboard/chart/visitor-chart.tsx +++ b/components/main/dashboard/chart/visitor-chart.tsx @@ -56,7 +56,6 @@ function getRangeAcrossMonths( const labels: string[] = []; const sortedData = data.sort((a, b) => a.month - b.month); - console.log("sorted data", sortedData); for (const monthData of sortedData) { const { month, view: v, comment: c, share: s } = monthData; @@ -106,16 +105,11 @@ const ApexChartColumnVisitors = (props: { const splitDate = date.split(" "); const splitDateDaily = String(range.start.year); let data = []; - console.log( - "aaawwww", - type === "monthly" && splitDate[1] === years, - type === "daily" && splitDateDaily === years - ); + if ( (type === "monthly" && splitDate[1] === years) || (type === "daily" && splitDateDaily === years) ) { - console.log("if", datas); data = datas; } else { const res = await getStatisticMonthly( @@ -124,7 +118,6 @@ const ApexChartColumnVisitors = (props: { data = res?.data?.data; setDatas(data); } - console.log("datas", data); const getDatas = data?.find( (a: any) => a.month == Number(splitDate[0]) && a.year === Number(splitDate[1]) diff --git a/components/main/dashboard/dashboard-container.tsx b/components/main/dashboard/dashboard-container.tsx index 43c5405..8ffb9ec 100644 --- a/components/main/dashboard/dashboard-container.tsx +++ b/components/main/dashboard/dashboard-container.tsx @@ -69,6 +69,7 @@ import { 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"; type ArticleData = Article & { no: number; @@ -198,7 +199,11 @@ export default function DashboardContainer() { today ); const [visitorDailyDate, setVisitorDailyDate] = useState({ - start: parseDate(convertDateFormatNoTimeV2(today)), + start: parseDate( + convertDateFormatNoTimeV2( + new Date(new Date().setDate(new Date().getDate() - 30)) + ) + ), end: parseDate(convertDateFormatNoTimeV2(today)), }); @@ -722,7 +727,7 @@ export default function DashboardContainer() { )} -
+
@@ -861,11 +866,9 @@ export default function DashboardContainer() {
-
+
-
- Visitor Analytics -
+
Users Analytics
+ e.target.value !== "" && + setTypeDateVisitor(e.target.value) + } + > + Bulanan + Harian + + + {typeDateVisitor === "monthly" ? ( + + + + + +
+ + + {year} + + +
+ +
+ {months.map((month, idx) => ( + + ))} +
+
+
+ ) : ( +
+ e !== null && setVisitorDailyDate(e)} + label="" + /> +
+ )} +
+
+
+
+ +
+
)}