diff --git a/package.json b/package.json index 1f9989b..d6134b9 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,13 @@ "dependencies": { "@reduxjs/toolkit": "^2.5.1", "@tanstack/react-query": "^5.66.0", + "apexcharts": "^4.5.0", "axios": "^1.7.9", "cra-template": "1.2.0", "formik": "^2.4.6", "react": "^19.0.0", + "react-apexcharts": "^1.7.0", + "react-countup": "^6.5.3", "react-dom": "^19.0.0", "react-icons": "^5.4.0", "react-redux": "^9.2.0", diff --git a/src/components/CustomCounter.jsx b/src/components/CustomCounter.jsx index dbfdf98..a9fa37d 100644 --- a/src/components/CustomCounter.jsx +++ b/src/components/CustomCounter.jsx @@ -1,29 +1,39 @@ -import React, { useEffect, useState } from 'react'; +// import React, { useEffect, useState } from 'react'; + +// const CustomCounter = ({ targetNumber, timeInSeconds }) => { +// const [count, setCount] = useState(0); + +// useEffect(() => { +// if (targetNumber <= 0 || timeInSeconds <= 0) return; // Handle edge cases + +// const interval = Math.floor(timeInSeconds * 1000 / targetNumber); // Time interval for each count in milliseconds +// const totalTime = timeInSeconds * 1000; // Total time for the entire count in milliseconds + +// let currentCount = 0; +// const intervalId = setInterval(() => { +// currentCount++; +// setCount((prevCount) => prevCount + 1); // Update state using the previous state + +// if (currentCount >= targetNumber) { +// clearInterval(intervalId); // Stop the counting when the target number is reached +// } +// }, interval); + +// // Cleanup the interval on component unmount +// return () => clearInterval(intervalId); +// }, [targetNumber, timeInSeconds]); + +// return <>{count}; +// }; + +// export default CustomCounter; + + +import React from 'react'; +import CountUp from 'react-countup'; const CustomCounter = ({ targetNumber, timeInSeconds }) => { - const [count, setCount] = useState(0); - - useEffect(() => { - if (targetNumber <= 0 || timeInSeconds <= 0) return; // Handle edge cases - - const interval = Math.floor(timeInSeconds * 1000 / targetNumber); // Time interval for each count in milliseconds - const totalTime = timeInSeconds * 1000; // Total time for the entire count in milliseconds - - let currentCount = 0; - const intervalId = setInterval(() => { - currentCount++; - setCount((prevCount) => prevCount + 1); // Update state using the previous state - - if (currentCount >= targetNumber) { - clearInterval(intervalId); // Stop the counting when the target number is reached - } - }, interval); - - // Cleanup the interval on component unmount - return () => clearInterval(intervalId); - }, [targetNumber, timeInSeconds]); - - return <>{count}; + return ; }; -export default CustomCounter; +export default CustomCounter; \ No newline at end of file diff --git a/src/components/breadcrumb/BreadcrumbCom.jsx b/src/components/breadcrumb/BreadcrumbCom.jsx index b47898e..5ff71a3 100644 --- a/src/components/breadcrumb/BreadcrumbCom.jsx +++ b/src/components/breadcrumb/BreadcrumbCom.jsx @@ -25,7 +25,7 @@ export default function BreadcrumbCom({title, span, paths}) { return ( // ${stickNav ? 'sticky top-0 transition-[top] duration-1000 shadow-md shadow-black' : '-top-[100px] static'} -
+
diff --git a/src/components/home/Widget1.jsx b/src/components/home/Widget1.jsx new file mode 100644 index 0000000..eba57a9 --- /dev/null +++ b/src/components/home/Widget1.jsx @@ -0,0 +1,187 @@ +import {useEffect, useRef} from 'react' +import ApexCharts from 'apexcharts' + +const Widget1 = ({chartHeight='50px'}) => { + const chartRef = useRef(null) + + const {mode} = '' // to be replaced by theme mode value later + + useEffect(() => { + const chart = refreshChart() + + return () => { + if (chart) { + chart.destroy() + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [chartRef, mode]) + + const refreshChart = () => { + if (!chartRef.current) { + return + } + + const chart = new ApexCharts(chartRef.current, chartOptions(chartHeight)) + if (chart) { + chart.render() + } + + return chart + } + + return ( +
+ {/* end::Title */} +
+
+ ) +} + +const chartOptions = (chartHeight) => { + // const labelColor = getCSSVariableValue('--bs-gray-800') + // const strokeColor = getCSSVariableValue('--bs-gray-300') + const labelColor = '#e9e9e9' + const strokeColor = '#e3e3e3' + // const strokeColor = getCSSVariableValue('--bs-gray-300') as string + + return { + series: [ + { + name: 'Net Profit', + data: [15, 25, 15, 40, 20, 50], + }, + ], + grid: { + show: false, + padding: { + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + }, + chart: { + fontFamily: 'inherit', + type: 'area', + height: chartHeight, + toolbar: { + show: false, + }, + zoom: { + enabled: false, + }, + sparkline: { + enabled: true, + }, + }, + plotOptions: {}, + legend: { + show: false, + }, + dataLabels: { + enabled: false, + }, + fill: { + type: 'gradient', + gradient: { + opacityFrom: 0.4, + opacityTo: 0, + stops: [20, 120, 120, 120], + }, + }, + stroke: { + curve: 'smooth', + show: true, + width: 3, + colors: ['#FFFFFF'], + }, + xaxis: { + categories: ['Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'], + axisBorder: { + show: false, + }, + axisTicks: { + show: false, + }, + labels: { + show: false, + style: { + colors: labelColor, + fontSize: '12px', + }, + }, + crosshairs: { + show: false, + position: 'front', + stroke: { + color: strokeColor, + width: 1, + dashArray: 3, + }, + }, + tooltip: { + enabled: true, + formatter: undefined, + offsetY: 0, + style: { + fontSize: '12px', + }, + }, + }, + yaxis: { + min: 0, + max: 60, + labels: { + show: false, + style: { + colors: labelColor, + fontSize: '12px', + }, + }, + }, + states: { + normal: { + filter: { + type: 'none', + value: 0, + }, + }, + hover: { + filter: { + type: 'none', + value: 0, + }, + }, + active: { + allowMultipleDataPointsSelection: false, + filter: { + type: 'none', + value: 0, + }, + }, + }, + tooltip: { + style: { + fontSize: '12px', + }, + y: { + formatter: function (val) { + return '$' + val + ' thousands' + }, + }, + }, + colors: ['#ffffff'], + markers: { + colors: [labelColor], + strokeColors: [strokeColor], + strokeWidth: 3, + }, + } +} + +export {Widget1} diff --git a/src/components/home/Widget2.jsx b/src/components/home/Widget2.jsx new file mode 100644 index 0000000..2afe810 --- /dev/null +++ b/src/components/home/Widget2.jsx @@ -0,0 +1,147 @@ +import {useEffect, useRef} from 'react' +import ApexCharts from 'apexcharts' + +const Widget2 = ({chartHeight='100px'}) => { + const chartRef = useRef(null) + + const {mode} = '' // to be replaced by theme mode value later + + useEffect(() => { + const chart = refreshChart() + + return () => { + if (chart) { + chart.destroy() + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [chartRef, mode]) + + const refreshChart = () => { + if (!chartRef.current) { + return + } + + const chart = new ApexCharts(chartRef.current, chartOptions(chartHeight)) + if (chart) { + chart.render() + } + + return chart + } + + return ( +
+ {/* end::Title */} +
+
+ ) +} + +const chartOptions = (chartHeight) => { + // const labelColor = getCSSVariableValue('--bs-gray-800') + + return { + series: [ + { + name: 'Inflation', + data: [1, 2.1, 1, 2.1, 4.1, 6.1, 4.1, 4.1, 2.1, 4.1, 2.1, 3.1, 1, 1, 2.1], + }, + ], + chart: { + fontFamily: 'inherit', + height: chartHeight, + type: 'bar', + toolbar: { + show: false, + }, + }, + grid: { + show: false, + padding: { + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + }, + colors: ['#ffffff'], + plotOptions: { + bar: { + borderRadius: 2.5, + dataLabels: { + position: 'top', // top, center, bottom + }, + columnWidth: '20%', + }, + }, + dataLabels: { + enabled: false, + formatter: function (val) { + return val + '%' + }, + offsetY: -20, + style: { + fontSize: '12px', + colors: ['#304758'], + }, + }, + xaxis: { + labels: { + show: false, + }, + categories: [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + 'Jan', + 'Feb', + 'Mar', + ], + position: 'top', + axisBorder: { + show: false, + }, + axisTicks: { + show: false, + }, + crosshairs: { + show: false, + }, + tooltip: { + enabled: false, + }, + }, + yaxis: { + show: false, + axisBorder: { + show: false, + }, + axisTicks: { + show: false, + // background: labelColor, + }, + labels: { + show: false, + formatter: function (val) { + return val + '%' + }, + }, + }, + } + } + +export {Widget2} diff --git a/src/components/layouts/DashboardLayout.jsx b/src/components/layouts/DashboardLayout.jsx index b065c3a..308879c 100644 --- a/src/components/layouts/DashboardLayout.jsx +++ b/src/components/layouts/DashboardLayout.jsx @@ -29,7 +29,7 @@ export default function DashboardLayout() {
-
+
diff --git a/src/index.css b/src/index.css index 8af8def..3bec06a 100644 --- a/src/index.css +++ b/src/index.css @@ -29,7 +29,7 @@ code { @apply [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 dark:[&::-webkit-scrollbar-track]:bg-neutral-700 dark:[&::-webkit-scrollbar-thumb]:bg-neutral-500 [&::-webkit-scrollbar-track]:rounded-full [&::-webkit-scrollbar-thumb]:rounded-full } .box { - @apply flex flex-col gap-8 w-full p-8 cursor-pointer rounded-lg h-full border-[1px] border-[#F1F1F4] dark:border-[#1E2027] shadow-[0px_3px_4px_0px_rgba(0,_0,_0,_0.03)] + @apply flex flex-col w-full p-8 cursor-pointer rounded-lg h-full border-[1px] border-[#F1F1F4] dark:border-[#1E2027] shadow-[0px_3px_4px_0px_rgba(0,_0,_0,_0.03)] } } diff --git a/src/pages/HomePage.jsx b/src/pages/HomePage.jsx index e90b8d8..c82a82b 100644 --- a/src/pages/HomePage.jsx +++ b/src/pages/HomePage.jsx @@ -4,15 +4,18 @@ import CustomCounter from '../components/CustomCounter' import Icons from '../components/Icons' import TableWrapper from '../components/tableWrapper/TableWrapper' import Avatar from '../assets/user_avatar.jpg' +import { Widget1 } from '../components/home/Widget1' +import { Widget2 } from '../components/home/Widget2' export default function HomePage() { return (
-
+

Earnings

+ {/* */}

$

- 12% this week

@@ -20,13 +23,14 @@ export default function HomePage() {

Contributions

+ {/* */}

+ 56% this week

-

Summary

+

Summary

@@ -68,7 +72,7 @@ export default function HomePage() {
-
+

Members Statistics