diff --git a/package-lock.json b/package-lock.json index 445a7be..be736fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "jsqr": "^1.4.0", "qrcode.react": "^3.1.0", "react": "^18.3.1", + "react-apexcharts": "^1.7.0", "react-bootstrap": "^2.10.4", "react-dom": "^18.3.1", "react-loader-spinner": "^6.1.6", @@ -28,7 +29,6 @@ "react-scripts": "5.0.1", "react-switch": "^7.0.0", "react-youtube": "^10.1.0", - "recharts": "^2.13.3", "smooth-scroll-into-view-if-needed": "^2.0.2", "socket.io-client": "^4.7.5", "styled-components": "^6.1.11", @@ -4049,6 +4049,62 @@ "string.prototype.matchall": "^4.0.6" } }, + "node_modules/@svgdotjs/svg.draggable.js": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.4.tgz", + "integrity": "sha512-vWi/Col5Szo74HJVBgMHz23kLVljt3jvngmh0DzST45iO2ubIZ487uUAHIxSZH2tVRyiaaTL+Phaasgp4gUD2g==", + "peer": true, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, + "node_modules/@svgdotjs/svg.filter.js": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.8.tgz", + "integrity": "sha512-YshF2YDaeRA2StyzAs5nUPrev7npQ38oWD0eTRwnsciSL2KrRPMoUw8BzjIXItb3+dccKGTX3IQOd2NFzmHkog==", + "peer": true, + "dependencies": { + "@svgdotjs/svg.js": "^3.1.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@svgdotjs/svg.js": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.4.tgz", + "integrity": "sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Fuzzyma" + } + }, + "node_modules/@svgdotjs/svg.resize.js": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz", + "integrity": "sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==", + "peer": true, + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.select.js": "^4.0.1" + } + }, + "node_modules/@svgdotjs/svg.select.js": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.2.tgz", + "integrity": "sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g==", + "peer": true, + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", @@ -4650,11 +4706,6 @@ "@types/node": "*" } }, - "node_modules/@types/d3-array": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", - "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" - }, "node_modules/@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", @@ -4665,11 +4716,6 @@ "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" - }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", @@ -4704,11 +4750,6 @@ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" - }, "node_modules/@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", @@ -5589,6 +5630,12 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", + "peer": true + }, "node_modules/@zxing/browser": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.7.tgz", @@ -5855,6 +5902,20 @@ "node": ">= 8" } }, + "node_modules/apexcharts": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.3.0.tgz", + "integrity": "sha512-PfvZQpv91T68hzry9l5zP3Gip7sQvF0nFK91uCBrswIKX7rbIdbVNS4fOks9m9yP3Ppgs6LHgU2M/mjoG4NM0A==", + "peer": true, + "dependencies": { + "@svgdotjs/svg.draggable.js": "^3.0.4", + "@svgdotjs/svg.filter.js": "^3.0.8", + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.resize.js": "^2.0.2", + "@svgdotjs/svg.select.js": "^4.0.1", + "@yr/monotone-cubic-spline": "^1.0.3" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -7551,14 +7612,6 @@ "node": ">=12" } }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "engines": { - "node": ">=12" - } - }, "node_modules/d3-format": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", @@ -7634,14 +7687,6 @@ "node": ">=12" } }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "engines": { - "node": ">=12" - } - }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -7729,11 +7774,6 @@ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" - }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -9239,14 +9279,6 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-equals": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", - "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -15832,6 +15864,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-apexcharts": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.7.0.tgz", + "integrity": "sha512-03oScKJyNLRf0Oe+ihJxFZliBQM9vW3UWwomVn4YVRTN1jsIR58dLWt0v1sb8RwJVHDMbeHiKQueM0KGpn7nOA==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "apexcharts": ">=4.0.0", + "react": ">=0.13" + } + }, "node_modules/react-app-polyfill": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", @@ -16245,20 +16289,6 @@ "node": ">=10" } }, - "node_modules/react-smooth": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz", - "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==", - "dependencies": { - "fast-equals": "^5.0.1", - "prop-types": "^15.8.1", - "react-transition-group": "^4.4.5" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, "node_modules/react-switch": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz", @@ -16334,41 +16364,6 @@ "node": ">=8.10.0" } }, - "node_modules/recharts": { - "version": "2.13.3", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.13.3.tgz", - "integrity": "sha512-YDZ9dOfK9t3ycwxgKbrnDlRC4BHdjlY73fet3a0C1+qGMjXVZe6+VXmpOIIhzkje5MMEL8AN4hLIe4AMskBzlA==", - "dependencies": { - "clsx": "^2.0.0", - "eventemitter3": "^4.0.1", - "lodash": "^4.17.21", - "react-is": "^18.3.1", - "react-smooth": "^4.0.0", - "recharts-scale": "^0.4.4", - "tiny-invariant": "^1.3.1", - "victory-vendor": "^36.6.8" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/recharts-scale": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", - "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", - "dependencies": { - "decimal.js-light": "^2.4.1" - } - }, - "node_modules/recharts/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, "node_modules/recursive-readdir": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", @@ -18231,11 +18226,6 @@ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -18740,27 +18730,6 @@ "node": ">= 0.8" } }, - "node_modules/victory-vendor": { - "version": "36.9.2", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", - "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", - "dependencies": { - "@types/d3-array": "^3.0.3", - "@types/d3-ease": "^3.0.0", - "@types/d3-interpolate": "^3.0.1", - "@types/d3-scale": "^4.0.2", - "@types/d3-shape": "^3.1.0", - "@types/d3-time": "^3.0.0", - "@types/d3-timer": "^3.0.0", - "d3-array": "^3.1.6", - "d3-ease": "^3.0.1", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.1.0", - "d3-time": "^3.0.0", - "d3-timer": "^3.0.1" - } - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index aadabfc..325f78f 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "jsqr": "^1.4.0", "qrcode.react": "^3.1.0", "react": "^18.3.1", + "react-apexcharts": "^1.7.0", "react-bootstrap": "^2.10.4", "react-dom": "^18.3.1", "react-loader-spinner": "^6.1.6", @@ -24,7 +25,6 @@ "react-scripts": "5.0.1", "react-switch": "^7.0.0", "react-youtube": "^10.1.0", - "recharts": "^2.13.3", "smooth-scroll-into-view-if-needed": "^2.0.2", "socket.io-client": "^4.7.5", "styled-components": "^6.1.11", diff --git a/src/components/BarChart.js b/src/components/BarChart.js index 264cdf7..9675955 100644 --- a/src/components/BarChart.js +++ b/src/components/BarChart.js @@ -1,48 +1,17 @@ import React, { useRef, useEffect } from 'react'; -import { BarChart, Bar, XAxis, Tooltip, Legend, CartesianGrid, ResponsiveContainer, LabelList } from 'recharts'; +import ReactApexChart from 'react-apexcharts'; // Colors palette const colors = [ - // **Analogous Colors** (near greens, yellows) - "#D0E14F", // Light green-yellow - "#B2B83D", // Olive yellow - "#A9C96E", // Muted olive green (your bg color itself) - "#A8B64E", // Olive green with yellow undertones - - // **Complementary Colors** (contrast with green) - "#FF6347", // Tomato red - "#FF4500", // Orange red - "#FF8C00", // Dark orange - "#FF7F50", // Coral - - // **Triadic Colors** (balanced vibrant combination) - "#1E90FF", // Dodger blue - "#FF00FF", // Magenta - "#32CD32", // Lime green - - // **Tetradic Colors** (4-color palette: 2 complementary pairs) - "#00CED1", // Dark turquoise - "#FFD700", // Gold - "#FF1493", // Deep pink - "#8A2BE2", // Blue violet - - // **Neutral Tones** (earthy, muted tones to balance the palette) - "#FFDAB9", // Peach - "#F0E68C", // Khaki - "#8B4513", // Saddle brown - "#4B0082", // Indigo - "#C71585", // Medium violet red - - // **Pastels for softer contrast** - "#FFB6C1", // Light pink - "#E6E6FA", // Lavender - "#98FB98", // Pale green - "#F0FFF0", // Honeydew - "#D3D3D3", // Light grey - ]; - + "#D0E14F", "#B2B83D", "#A9C96E", "#A8B64E", + "#FF6347", "#FF4500", "#FF8C00", "#FF7F50", + "#1E90FF", "#FF00FF", "#32CD32", + "#00CED1", "#FFD700", "#FF1493", "#8A2BE2", + "#FFDAB9", "#F0E68C", "#8B4513", "#4B0082", "#C71585", + "#FFB6C1", "#E6E6FA", "#98FB98", "#F0FFF0", "#D3D3D3" +]; -const SimpleBarChart = ({ Data }) => { +const SimpleLineChart = ({ Data }) => { const lastMonthRef = useRef(''); const lastYearRef = useRef(''); const usedColors = useRef([]); // Keep track of used colors @@ -54,23 +23,19 @@ const SimpleBarChart = ({ Data }) => { // Ensure Data is not null or undefined const transformedData = (Data?.length ? Data.reduce((acc, { date, materialId, priceAtp, stockDifference, name }) => { function isSameDay(date1, date2) { - const d1 = new Date(date1); - const d2 = new Date(date2); - - return d1.getFullYear() === d2.getFullYear() && - d1.getMonth() === d2.getMonth() && - d1.getDate() === d2.getDate(); + const d1 = new Date(date1); + const d2 = new Date(date2); + + return d1.getFullYear() === d2.getFullYear() && + d1.getMonth() === d2.getMonth() && + d1.getDate() === d2.getDate(); } - // Assuming `acc` is an array of entries and `date` is the input date you're checking const existingEntry = acc.find(d => isSameDay(d.date, date)); - console.log(existingEntry) if (existingEntry) { - // If it exists, sum the stockDifference (priceAtp * stockDifference) existingEntry[name] = (existingEntry[name] || 0) + (priceAtp * stockDifference); } else { - // If it doesn't exist yet, add a new entry acc.push({ date, materialId, @@ -78,123 +43,84 @@ const SimpleBarChart = ({ Data }) => { [name]: priceAtp * stockDifference }); } - return acc; }, []) : []); - // Sort the data by date (ascending) to easily find the oldest date const sortedData = [...transformedData].sort((a, b) => new Date(a.date) - new Date(b.date)); - - // The first date in the sorted array will be the oldest const oldestDate = sortedData[0]?.date; - - // Get the unique materials (names) from the data + const uniqueMaterials = Array.from(new Set(Data?.map(item => item.name) || [])); + const uniqueDates = Array.from(new Set(transformedData.map(item => item.date))); - // Function to format date and handle month and year changes - const formatDate = (date) => { - const formattedDate = new Date(date); - const day = formattedDate.getDate(); // Get the day of the month - const month = formattedDate.toLocaleString('en-US', { month: 'short' }); // Get the abbreviated month (e.g., "Nov") - const year = formattedDate.getFullYear().toString().slice(2); // Get the last two digits of the year (e.g., "24") - - // Extract the year from the first data point - const firstYear = new Date(sortedData[0]?.date).getFullYear(); - - // Check if all dates have the same year - const allSameYear = sortedData.every((item) => new Date(item.date).getFullYear() === firstYear); - - // If all dates are from the same year, show only "day month" - if (allSameYear && formattedDate.toLocaleString('en-US', { month: 'short' }) !== lastMonthRef.current) { - lastMonthRef.current = formattedDate.toLocaleString('en-US', { month: 'short' }); - // Show just the day and month if all dates have the same year - return `${day} ${month}`; - } - // if (allSameYear) { - // // Show just the day and month if all dates have the same year - // return `${day} ${month}`; - // } - - // Check if it's the oldest date (first entry) - if (date === oldestDate) { - lastMonthRef.current = formattedDate.toLocaleDateString('en-US', { month: 'short' }); - lastYearRef.current = formattedDate.getFullYear(); - return `${day} ${month} ${year}`; // Format as "day month year" (e.g., "4 Nov 24") - } - - // If the year changes, show the full date with year - if (formattedDate.getFullYear() !== lastYearRef.current) { - lastYearRef.current = formattedDate.getFullYear(); - return `${day} ${month} ${year}`; // Show full date: day month year - } - - // If the month changes, show the full date with month and year - if (formattedDate.toLocaleString('en-US', { month: 'short' }) !== lastMonthRef.current) { - lastMonthRef.current = formattedDate.toLocaleString('en-US', { month: 'short' }); - return `${day} ${month} `; // Show full date: day month year - } - - // Only show the day if the month hasn't changed - return `${day}`; // Show just the day if the month remains the same - }; - - - // Function to get the next available color from the palette, starting from a random index const getNextColor = () => { - // Randomly pick a starting index from the color palette const randomIndex = Math.floor(Math.random() * colors.length); - - // Find the first unused color from the random starting point let color = null; for (let i = 0; i < colors.length; i++) { const index = (randomIndex + i) % colors.length; if (!usedColors.current.includes(colors[index])) { color = colors[index]; - usedColors.current.push(color); // Mark color as used + usedColors.current.push(color); break; } } - - return color || '#000000'; // Fallback color if no colors are available + return color || '#000000'; }; - // Extract unique dates for the XAxis - const uniqueDates = Array.from(new Set(transformedData.map(item => item.date))); + // Prepare data for ApexCharts + const series = uniqueMaterials.map((material) => { + return { + name: material, + data: transformedData.map(item => item[material] || 0) + }; + }); + + const options = { + chart: { + type: 'line', + height: '100%', + zoom: { + enabled: true + } + }, + xaxis: { + categories: uniqueDates, + labels: { + style: { + fontSize: '12px', + } + } + }, + colors: uniqueMaterials.map(() => getNextColor()), // Assign unique colors for each material + legend: { + position: 'top', + horizontalAlign: 'center', + itemMargin: { + horizontal: 10, + vertical: 0 + }, + labels: { + colors: '#3498db', // Set legend text color + }, + }, + tooltip: { + theme: 'light', + style: { + fontSize: '14px', + color: '#3498db' + } + } + }; return (
{formatIncome(selectedItems?.report.totalIncome)}
+{formatIncome(selectedItems?.report?.totalIncome)}
pemasukan
{formatIncome(selectedItems?.report.currentOutcome)}
+{formatIncome(selectedItems?.report?.currentOutcome)}
pengeluaran