fix:dashboard map 38 prov

This commit is contained in:
Rama Priyanto 2025-06-26 13:01:49 +07:00
parent 686d29439c
commit 34b6586dd2
7 changed files with 41824 additions and 9390 deletions

View File

@ -69,98 +69,98 @@ export default function Login() {
error("Username & Password Wajib Diisi !"); error("Username & Password Wajib Diisi !");
} else { } else {
// login dengan otp // login dengan otp
// loading(); loading();
// const response: any = await emailValidation(data); const response: any = await emailValidation(data);
// if (response?.error) { if (response?.error) {
// console.log("error", response); console.log("error", response);
// if (response?.message?.messages[0]?.includes("failed to send mail")) { if (response?.message?.messages[0]?.includes("failed to send mail")) {
// error("Gagal Mengirim OTP"); error("Gagal Mengirim OTP");
// return false; return false;
// } }
// if (response?.message?.messages[0]?.includes("username")) { if (response?.message?.messages[0]?.includes("username")) {
// error("Username / Password Tidak Sesuai"); error("Username / Password Tidak Sesuai");
// return false; return false;
// } }
// error("Unknown Error"); error("Unknown Error");
// return false; return false;
// } }
// close(); close();
// if (response?.data?.messages[0] === "Continue to setup email") { if (response?.data?.messages[0] === "Continue to setup email") {
// setFirstLogin(true); setFirstLogin(true);
// } else { } else {
// setNeedOtp(true); setNeedOtp(true);
// } }
// login tanpa otp // login tanpa otp
loading(); // loading();
const response = await postSignIn(data); // const response = await postSignIn(data);
if (response?.error) { // if (response?.error) {
error("Username / Password Tidak Sesuai"); // error("Username / Password Tidak Sesuai");
} else { // } else {
const profile = await getProfile(response?.data?.data?.access_token); // const profile = await getProfile(response?.data?.data?.access_token);
const dateTime: any = new Date(); // 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, { // Cookies.set("access_token", response?.data?.data?.access_token, {
expires: 1, // expires: 1,
}); // });
Cookies.set("refresh_token", response?.data?.data?.refresh_token, { // Cookies.set("refresh_token", response?.data?.data?.refresh_token, {
expires: 1, // expires: 1,
}); // });
Cookies.set("time_refresh", newTime, { // Cookies.set("time_refresh", newTime, {
expires: 1, // expires: 1,
}); // });
Cookies.set("is_first_login", "true", { // Cookies.set("is_first_login", "true", {
secure: true, // secure: true,
sameSite: "strict", // sameSite: "strict",
}); // });
const resActivity = await saveActivity( // const resActivity = await saveActivity(
{ // {
activityTypeId: 1, // activityTypeId: 1,
url: "https://kontenhumas.com/auth", // url: "https://kontenhumas.com/auth",
userId: profile?.data?.data?.id, // userId: profile?.data?.data?.id,
}, // },
accessData?.id_token // accessData?.id_token
); // );
Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, { // Cookies.set("profile_picture", profile?.data?.data?.profilePictureUrl, {
expires: 1, // expires: 1,
}); // });
Cookies.set("uie", profile?.data?.data?.id, { // Cookies.set("uie", profile?.data?.data?.id, {
expires: 1, // expires: 1,
}); // });
Cookies.set("ufne", profile?.data?.data?.fullname, { // Cookies.set("ufne", profile?.data?.data?.fullname, {
expires: 1, // expires: 1,
}); // });
Cookies.set("ulie", profile?.data?.data?.userLevelGroup, { // Cookies.set("ulie", profile?.data?.data?.userLevelGroup, {
expires: 1, // expires: 1,
}); // });
Cookies.set("username", profile?.data?.data?.username, { // Cookies.set("username", profile?.data?.data?.username, {
expires: 1, // expires: 1,
}); // });
Cookies.set("urie", profile?.data?.data?.userRoleId, { // Cookies.set("urie", profile?.data?.data?.userRoleId, {
expires: 1, // expires: 1,
}); // });
Cookies.set("masterPoldaId", profile?.data?.data?.masterPoldaId, { // Cookies.set("masterPoldaId", profile?.data?.data?.masterPoldaId, {
expires: 1, // expires: 1,
}); // });
Cookies.set("ulne", profile?.data?.data?.userLevelId, { // Cookies.set("ulne", profile?.data?.data?.userLevelId, {
expires: 1, // expires: 1,
}); // });
// Cookies.set("urce", profile?.data?.data?.roleCode, { // // 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, // expires: 1,
// }); // });
Cookies.set("email", profile?.data?.data?.email, {
expires: 1,
});
router.push("/admin/dashboard");
Cookies.set("status", "login", {
expires: 1,
});
close(); // close();
} // }
} }
}; };

View File

@ -68,7 +68,7 @@ import {
} from "@/components/icons"; } from "@/components/icons";
import { format } from "date-fns"; import { format } from "date-fns";
import ApexChartColumnVisitors from "./chart/visitor-chart"; import ApexChartColumnVisitors from "./chart/visitor-chart";
import { IndonesiaMap } from "@/components/ui/maps-charts"; import IndonesiaMap from "@/components/ui/maps-charts";
import ApexChartDynamic from "./chart/dynamic-bar-char"; import ApexChartDynamic from "./chart/dynamic-bar-char";
type ArticleData = Article & { type ArticleData = Article & {
@ -115,16 +115,49 @@ const months = [
"Dec", "Dec",
]; ];
const dummyData = [ const rawData = [
{ name: "DI. ACEH", value: 10, id: 1 }, { name: "Aceh", value: 32 },
{ name: "SUMATERA UTARA", value: 20, id: 2 }, { name: "Sumatera Utara", value: 78 },
{ name: "DKI JAKARTA", value: 100, id: 3 }, { name: "Sumatera Barat", value: 45 },
{ name: "JAWA BARAT", value: 30, id: 4 }, { name: "Riau", value: 63 },
{ name: "IRIAN JAYA TIMUR", value: 20, id: 5 }, { name: "Jambi", value: 21 },
{ name: "Sumatera Selatan", value: 56 },
{ name: "Bengkulu", value: 11 },
{ name: "Lampung", value: 49 },
{ name: "Kepulauan Bangka Belitung", value: 27 },
{ name: "Kepulauan Riau", value: 19 },
{ name: "DKI Jakarta", value: 97 },
{ name: "Jawa Barat", value: 84 },
{ name: "Jawa Tengah", value: 88 },
{ name: "Daerah Istimewa Yogyakarta", value: 36 },
{ name: "Jawa Timur", value: 91 },
{ name: "Banten", value: 52 },
{ name: "Bali", value: 66 },
{ name: "Nusa Tenggara Barat", value: 40 },
{ name: "Nusa Tenggara Timur", value: 59 },
{ name: "Kalimantan Barat", value: 61 },
{ name: "Kalimantan Tengah", value: 29 },
{ name: "Kalimantan Selatan", value: 71 },
{ name: "Kalimantan Timur", value: 76 },
{ name: "Kalimantan Utara", value: 18 },
{ name: "Sulawesi Utara", value: 55 },
{ name: "Sulawesi Tengah", value: 31 },
{ name: "Sulawesi Selatan", value: 80 },
{ name: "Sulawesi Tenggara", value: 34 },
{ name: "Gorontalo", value: 23 },
{ name: "Sulawesi Barat", value: 12 },
{ name: "Maluku", value: 25 },
{ name: "Maluku Utara", value: 30 },
{ name: "Papua", value: 37 },
{ name: "Papua Barat", value: 33 },
{ name: "Papua Tengah", value: 16 },
{ name: "Papua Pegunungan", value: 8 },
{ name: "Papua Selatan", value: 14 },
{ name: "Papua Barat Daya", value: 6 },
]; ];
const getTotalData: number[] = []; const getTotalData: number[] = [];
dummyData.map((list) => { rawData.map((list) => {
getTotalData.push(list.value); getTotalData.push(list.value);
}); });
@ -977,21 +1010,8 @@ export default function DashboardContainer() {
</div> </div>
{roleId && Number(roleId) < 3 && ( {roleId && Number(roleId) < 3 && (
<div> <div>
<div className="flex flex-col lg:flex-row gap-6 w-full pr-2 md:pr-0"> <IndonesiaMap data={rawData} />
<div className="w-screen md:w-[80%] h-[360px] lg:h-[600px]">
<IndonesiaMap />
</div>
<div className="w-screen md:w-[300px] h-[360px] lg:h-[600px] overflow-auto gap-2 flex flex-col">
{dummyData.map((list) => (
<div key={list.id} className="w-full flex flex-row gap-2">
<p className="w-1/2">{list.name}</p>{" "}
<p className="w-1/2 bg-[#0e7490] text-white border-white ">
{list.value}
</p>
</div>
))}
</div>
</div>
<div className="border-1 shadow-sm w-full rounded-lg p-6 flex flex-col mt-4 h-[600px]"> <div className="border-1 shadow-sm w-full rounded-lg p-6 flex flex-col mt-4 h-[600px]">
<div className="flex justify-between mb-3"> <div className="flex justify-between mb-3">
<div className="font-semibold flex flex-col"> <div className="font-semibold flex flex-col">

View File

@ -1,41 +1,16 @@
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef, useState } from "react";
import * as echarts from "echarts"; import * as echarts from "echarts";
import indonesiaGeo from "../../public/assets/geo/indonesia.json"; import indonesiaGeo from "../../public/assets/geo/indonesia.json";
export const IndonesiaMap: React.FC = () => { const IndonesiaMap = (props: { data: any }) => {
const chartRef = useRef<HTMLDivElement>(null); const chartRef = useRef<HTMLDivElement>(null);
const myChart = useRef<echarts.EChartsType | null>(null); const myChart = useRef<echarts.EChartsType | null>(null);
const [selectedProvince, setSelectedProvince] = useState("");
useEffect(() => { const selectedProvinceRef = useRef<string | null>(null);
if (!chartRef.current) return; const chartOptionRef = useRef<any>(null);
(window as any).echarts = echarts;
const fixedGeo = { const option = {
...indonesiaGeo,
features: indonesiaGeo.features.map((f) => ({
...f,
properties: {
...f.properties,
name: f.properties.Propinsi, // 🔥 inilah kuncinya
},
})),
};
echarts.registerMap("indonesia", fixedGeo as any);
const chart = echarts.init(chartRef.current);
myChart.current = chart;
const rawData = [
{ name: "DI. ACEH", value: 10 },
{ name: "SUMATERA UTARA", value: 20 },
{ name: "DKI JAKARTA", value: 100 },
{ name: "JAWA BARAT", value: 30 },
{ name: "IRIAN JAYA TIMUR", value: 20 },
];
console.log("raw", rawData);
chart.setOption({
backgroundColor: "#d3d3d3", backgroundColor: "#d3d3d3",
title: { title: {
text: "Sebaran Data", text: "Sebaran Data",
@ -48,18 +23,17 @@ export const IndonesiaMap: React.FC = () => {
show: true, show: true,
seriesIndex: 0, seriesIndex: 0,
inRange: { inRange: {
color: ["#ffffff", "#ff0000"], color: ["#ff0000", "#ffffff"],
}, },
}, },
series: [ series: [
{ {
type: "map", type: "map",
map: "indonesia", map: "indonesia",
// nameProperty: "properties.Propinsi", // harus cocok
roam: true, roam: true,
zoom: 1.2, zoom: 1.2,
center: [120, -2], center: [118, -2],
label: { label: {
show: false, show: false,
color: "#000", color: "#000",
@ -68,19 +42,96 @@ export const IndonesiaMap: React.FC = () => {
borderColor: "#999", borderColor: "#999",
}, },
emphasis: { emphasis: {
label: {
show: true,
color: "#000",
},
itemStyle: { itemStyle: {
areaColor: "#ffcccc", areaColor: "#ffcccc",
}, },
}, },
data: rawData, data: props.data,
}, },
], ],
};
useEffect(() => {
if (!chartRef.current) return;
(window as any).echarts = echarts;
const fixedGeo = {
...indonesiaGeo,
features: indonesiaGeo.features.map((f) => ({
...f,
properties: {
...f.properties,
name: f.properties.PROVINSI,
},
})),
};
echarts.registerMap("indonesia", fixedGeo as any);
const chart = echarts.init(chartRef.current);
myChart.current = chart;
chart.on("click", (params: any) => {
highlightProvince(params.name);
}); });
chartOptionRef.current = option;
chart.setOption(option);
return () => { return () => {
chart.dispose(); chart.dispose();
}; };
}, []); }, []);
return <div ref={chartRef} style={{ height: "100%", width: "100%" }} />; const highlightProvince = (name: string) => {
if (!myChart.current || !chartOptionRef.current) return;
myChart.current.clear();
myChart.current.setOption(chartOptionRef.current);
myChart.current.dispatchAction({
type: "highlight",
name,
});
myChart.current.dispatchAction({
type: "showTip",
name,
});
selectedProvinceRef.current = name;
};
return (
<div className="flex flex-col lg:flex-row gap-6 w-full pr-2 md:pr-0">
<div className="w-screen md:w-[70%] h-[360px] lg:h-[600px]">
<div ref={chartRef} style={{ height: "100%", width: "100%" }} />
</div>
<div className="w-screen md:w-[30%] h-[360px] lg:h-[600px] overflow-auto flex flex-col">
{props.data.map((list: any) => (
<a
key={list.name}
onClick={() => highlightProvince(list.name)}
className={`w-full flex flex-row cursor-pointer gap-2 ${
selectedProvince === list.name ? "bg-slate-300" : ""
}`}
>
<p className="w-4/5">{list.name}</p>{" "}
<p
className={`w-1/5 ${
selectedProvince === list.name ? "bg-slate-300" : "bg-[#a9d7e4]"
} text-black border-white text-center`}
>
{list.value}
</p>
</a>
))}
</div>
</div>
);
}; };
export default IndonesiaMap;

42
package-lock.json generated
View File

@ -31,6 +31,7 @@
"@types/react": "19.1.2", "@types/react": "19.1.2",
"@types/react-datepicker": "^6.0.1", "@types/react-datepicker": "^6.0.1",
"@types/react-dom": "19.1.2", "@types/react-dom": "19.1.2",
"@types/topojson-client": "^3.1.5",
"apexcharts": "^3.48.0", "apexcharts": "^3.48.0",
"autoprefixer": "10.4.16", "autoprefixer": "10.4.16",
"axios": "^1.6.8", "axios": "^1.6.8",
@ -70,6 +71,7 @@
"swiper": "^11.0.6", "swiper": "^11.0.6",
"tailwind-variants": "^0.1.18", "tailwind-variants": "^0.1.18",
"tailwindcss": "3.3.5", "tailwindcss": "3.3.5",
"topojson-client": "^3.1.0",
"typescript": "5.0.4", "typescript": "5.0.4",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"zod": "^3.23.8", "zod": "^3.23.8",
@ -9425,6 +9427,11 @@
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
"dev": true "dev": true
}, },
"node_modules/@types/geojson": {
"version": "7946.0.16",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="
},
"node_modules/@types/glob": { "node_modules/@types/glob": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
@ -9524,6 +9531,23 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/topojson-client": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@types/topojson-client/-/topojson-client-3.1.5.tgz",
"integrity": "sha512-C79rySTyPxnQNNguTZNI1Ct4D7IXgvyAs3p9HPecnl6mNrJ5+UhvGNYcZfpROYV2lMHI48kJPxwR+F9C6c7nmw==",
"dependencies": {
"@types/geojson": "*",
"@types/topojson-specification": "*"
}
},
"node_modules/@types/topojson-specification": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.5.tgz",
"integrity": "sha512-C7KvcQh+C2nr6Y2Ub4YfgvWvWCgP2nOQMtfhlnwsRL4pYmmwzBS7HclGiS87eQfDOU/DLQpX6GEscviaz4yLIQ==",
"dependencies": {
"@types/geojson": "*"
}
},
"node_modules/@types/trusted-types": { "node_modules/@types/trusted-types": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
@ -17596,6 +17620,24 @@
"node": ">=8.0" "node": ">=8.0"
} }
}, },
"node_modules/topojson-client": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
"integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
"dependencies": {
"commander": "2"
},
"bin": {
"topo2geo": "bin/topo2geo",
"topomerge": "bin/topomerge",
"topoquantize": "bin/topoquantize"
}
},
"node_modules/topojson-client/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",

View File

@ -32,6 +32,7 @@
"@types/react": "19.1.2", "@types/react": "19.1.2",
"@types/react-datepicker": "^6.0.1", "@types/react-datepicker": "^6.0.1",
"@types/react-dom": "19.1.2", "@types/react-dom": "19.1.2",
"@types/topojson-client": "^3.1.5",
"apexcharts": "^3.48.0", "apexcharts": "^3.48.0",
"autoprefixer": "10.4.16", "autoprefixer": "10.4.16",
"axios": "^1.6.8", "axios": "^1.6.8",
@ -71,6 +72,7 @@
"swiper": "^11.0.6", "swiper": "^11.0.6",
"tailwind-variants": "^0.1.18", "tailwind-variants": "^0.1.18",
"tailwindcss": "3.3.5", "tailwindcss": "3.3.5",
"topojson-client": "^3.1.0",
"typescript": "5.0.4", "typescript": "5.0.4",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"zod": "^3.23.8", "zod": "^3.23.8",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff