DEV Community

Navnit Rai
Navnit Rai

Posted on

Dashboard.jsx

import {
  Box,
  Grid,
  Heading,
  HStack,
  Progress,
  Stack,
  Text,
} from '@chakra-ui/react'; // Importing Chakra UI components for styling
import React, { useEffect } from 'react'; // Importing React and useEffect hook
import { RiArrowDownLine, RiArrowUpLine } from 'react-icons/ri'; // Importing arrow icons for profit indication
import cursor from '../../../assets/images/cursor.png'; // Custom cursor image
import Sidebar from '../Sidebar'; // Importing Sidebar component
import { DoughnutChart, LineChart } from './Chart'; // Importing chart components
import { useDispatch, useSelector } from 'react-redux'; // For accessing Redux store
import { getDashboardStats } from '../../../redux/actions/admin'; // Action to fetch dashboard statistics
import Loader from '../../Layout/Loader/Loader'; // Loader component for loading state
import toast from 'react-hot-toast'; // Toast notifications

// Databox component for displaying individual statistics
const Databox = ({ title, qty, qtyPercentage, profit }) => (
  <Box
    w={['full', '20%']} // Responsive width
    boxShadow={'-2px 0 10px rgba(107,70,193,0.5)'} // Box shadow for visual effect
    p="8" // Padding
    borderRadius={'lg'} // Rounded corners
  >
    <Text children={title} /> // Title of the Databox
    <HStack spacing={'6'}> // Horizontal stack for quantity and percentage
      <Text fontSize={'2xl'} fontWeight="bold" children={qty} /> // Quantity display
      <HStack>
        <Text children={`${qtyPercentage}%`} /> // Percentage change display
        {profit ? ( // Profit indicator
          <RiArrowUpLine color="green" /> // Green arrow for profit
        ) : (
          <RiArrowDownLine color="red" /> // Red arrow for loss
        )}
      </HStack>
    </HStack>
    <Text opacity={0.6} children={'Since Last Month'} /> // Additional info text
  </Box>
);

// Bar component for progress bars
const Bar = ({ title, value, profit }) => (
  <Box py="4" px={['0', '20']}> // Padding
    <Heading size="sm" children={title} mb="2" /> // Title of the progress bar
    <HStack w="full" alignItems={'center'}> // Horizontal stack for value and progress bar
      <Text children={profit ? '0%' : `-${value}%`} /> // Displaying percentage change
      <Progress w="full" value={profit ? value : 0} colorScheme="purple" /> // Progress bar
      <Text children={`${value > 100 ? value : 100}%`} /> // Displaying total value
    </HStack>
  </Box>
);

// Main Dashboard component
const Dashboard = () => {
  const dispatch = useDispatch(); // Hook to access dispatch function

  // Extracting data from Redux store
  const {
    loading,
    stats,
    viewsCount,
    subscriptionCount,
    usersCount,
    subscriptionPercentage,
    viewsPercentage,
    usersPercentage,
    subscriptionProfit,
    viewsProfit,
    usersProfit,
    error, // Error state (added for handling)
  } = useSelector(state => state.admin);

  // Fetching dashboard stats on component mount
  useEffect(() => {
    const fetchStats = async () => {
      try {
        await dispatch(getDashboardStats()); // Dispatching action to fetch stats
      } catch (error) {
        toast.error('Failed to load dashboard stats'); // Error handling with toast notification
      }
    };
    fetchStats(); // Calling the fetch function
  }, [dispatch]);

  return (
    <Grid
      css={{
        cursor: `url(${cursor}), default`, // Custom cursor style
      }}
      minH={'100vh'} // Minimum height for the grid
      templateColumns={['1fr', '5fr 1fr']} // Responsive template columns
    >
      {loading || !stats ? ( // Loading state check
        <Loader color="purple.500" /> // Loader component displayed while loading
      ) : (
        <Box boxSizing="border-box" py="16" px={['4', '0']}> // Main content box
          <Text
            textAlign={'center'}
            opacity={0.5}
            children={`Last change was on ${String(new Date(stats[11].createdAt)).split('G')[0]}`} // Displaying last change date
          />

          <Heading
            children="Dashboard" // Main heading
            ml={['0', '16']}
            mb="16"
            textAlign={['center', 'left']}
          />

          <Stack
            direction={['column', 'row']} // Responsive direction for the stack
            minH="24" // Minimum height for the stack
            justifyContent={'space-evenly'} // Space evenly between items
          >
            <Databox title="Views" qty={viewsCount} qtyPercentage={viewsPercentage} profit={viewsProfit} />
            <Databox title="Users" qty={usersCount} qtyPercentage={usersPercentage} profit={usersProfit} />
            <Databox title="Subscription" qty={subscriptionCount} qtyPercentage={subscriptionPercentage} profit={subscriptionProfit} />
          </Stack>

          <Box
            m={['0', '16']} // Margin
            borderRadius="lg" // Rounded corners
            p={['0', '16']} // Padding
            mt={['4', '16']} // Margin top
            boxShadow={'-2px 0 10px rgba(107,70,193,0.5)'} // Box shadow for visual effect
          >
            <Heading
              textAlign={['center', 'left']} // Responsive text alignment
              size="md"
              children="Views Graph" // Graph heading
              pt={['8', '0']} // Padding top
              ml={['0', '16']} // Margin left
            />
            <LineChart views={stats.map(item => item.views)} /> // Rendering line chart with views data
          </Box>

          <Grid templateColumns={['1fr', '2fr 1fr']}> // Responsive grid layout
            <Box p="4"> // Padding
              <Heading
                textAlign={['center', 'left']} // Responsive text alignment
                size="md"
                children="Progress Bar" // Progress bar heading
                my="8" // Margin y-axis
                ml={['0', '16']} // Margin left
              />
              <Box>
                <Bar profit={viewsProfit} title="Views" value={viewsPercentage} />
                <Bar profit={usersProfit} title="Users" value={usersPercentage} />
                <Bar profit={subscriptionProfit} title="Subscription" value={subscriptionPercentage} />
              </Box>
            </Box>

            <Box p={['0', '16']} boxSizing="border-box" py="4"> // Right box for doughnut chart
              <Heading textAlign={'center'} size="md" mb="4" children="Users" /> // Doughnut chart heading
              <DoughnutChart users={[subscriptionCount, usersCount - subscriptionCount]} /> // Rendering doughnut chart
            </Box>
          </Grid>
        </Box>
      )}
      <Sidebar /> // Rendering Sidebar component
    </Grid>
  );
};

export default Dashboard; // Exporting Dashboard component

Enter fullscreen mode Exit fullscreen mode

Top comments (0)