components_activity_index.jsx

import '../../utils/style/_activity.scss'
import Loader from '../../components/loader'
import PropTypes from 'prop-types'

import {
  Bar,
  BarChart,
  CartesianGrid,
  Legend,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts'

/**
 * Component that displays a chart showing daily activity.
 * @namespace
 * @component
 * @author  Pierre-Yves Léglise <pleglise@pm.me>
 * @see {@link https://recharts.org/en-US/api/BarChart} for further information on `BarChart` element from recharts api
 * @example
 * const dataActivity = {isLoading: false, data[{day:1, kilogram: 80, calories:240},...]}
 * return (
 *  <Activity dataActivity={userActivity} />
 * )
 * @prop {Object}     dataActivity                   The props passed to the component.
 * @prop {boolean}    dataActivity.isLoading         False if all the data have been fetched
 * @prop {object[]}   dataActivity.data              An array of objects containing data for the chart. `{day: number, kilogram: number, calories:number}`
 * @prop {number}     dataActivity.data[].day        Day's number of the activity
 * @prop {number}     dataActivity.data[].kilogram   Kilogram of the activity
 * @prop {number}     dataActivity.data[].calories   Calories  of the activity
 * @returns {JSX.Element}                            A JSX element containing a `BarChart` element from the `recharts` library.
 */
const Activity = ({ dataActivity }) => {
  /**
   * Displays a custom legend for a chart.
   *
   * @component
   * @author  Pierre-Yves Léglise <pleglise@pm.me>
   * @example
   * return{
   *  <LegendCustom />
   * }
   * @returns {JSX.Element} A JSX element representing the custom legend.
   */
  const LegendCustom = () => {
    return (
      <div className="legendCustom">
        <h3>Activité quotidienne</h3>
        <div className="bar-legend">
          <p>Poids (kg)</p>
          <p>Calories brulées (kCal)</p>
        </div>
      </div>
    )
  }
  /**
   * Displays a custom tooltip for a chart.
   *
   * @component
   * @author  Pierre-Yves Léglise <pleglise@pm.me>
   * @example
   * return{
   *  <SpecialTooltip />
   * }
   * @prop {boolean} active         Whether or not the tooltip is active.
   * @prop {Array} payload          An array of objects containing data for the chart.
   * @returns {null|JSX.Element}  A JSX element representing the custom tooltip. If the `active` property is `true` and the `payload` array exists and is not empty, the element is a list element containing the text returned by the `TooltipText` function.
   */
  const SpecialTooltip = ({ payload, active }) => {
    if (active) {
      return (
        <div className="tooltipSpecial">
          <p>{`${payload[0].value}kg`}</p>
          <p>{`${payload[1].value}kCal`}</p>
        </div>
      )
    }
    return null
  }
  const { isLoading } = dataActivity

  return (
    <>
      {isLoading ? (
        <Loader />
      ) : (
        <div className="activity-container">
          <ResponsiveContainer
            title="Activité quotidienne"
            width="100%"
            height="100%"
          >
            <BarChart
              data={dataActivity.data}
              margin={{
                top: 23,
                right: 30,
                left: 30,
                bottom: 23,
              }}
            >
              <CartesianGrid strokeDasharray="3" vertical={false} />
              <XAxis
                dataKey="day"
                tickCount="10"
                tickLine={false}
                tick={{ fontSize: 14 }}
              />
              <YAxis
                dataKey="kilogram"
                yAxisId="kilogram"
                axisLine={false}
                domain={['dataMin-1', 'dataMax+2']}
                tickCount="3"
                tickLine={false}
                tick={{ fontSize: 14 }}
                orientation="right"
              />
              <YAxis
                dataKey="calories"
                yAxisId="calories"
                type="number"
                hide={true}
              />
              <Legend
                layout="horizontal"
                content={<LegendCustom />}
                verticalAlign="top"
              />
              <Tooltip
                labelFormatter={() => ''}
                cursor={{ fill: '#DFDFDF', opacity: '0.6' }}
                content={<SpecialTooltip />}
                wrapperStyle={{ outline: 'none' }}
              />
              <Bar
                dataKey="kilogram"
                yAxisId="kilogram"
                fill="black"
                radius={[10, 10, 0, 0]}
                barSize={10}
              />
              <Bar
                dataKey="calories"
                yAxisId="calories"
                fill="red"
                radius={[10, 10, 0, 0]}
                barSize={10}
              />
            </BarChart>
          </ResponsiveContainer>
        </div>
      )}
    </>
  )
}
export default Activity

Activity.propTypes = {
  dataActivity: PropTypes.shape({
    isLoading: PropTypes.bool.isRequired,
    data: PropTypes.arrayOf(
      PropTypes.shape({
        day: PropTypes.number,
        kilogram: PropTypes.number,
        calories: PropTypes.number,
      })
    ).isRequired,
  }).isRequired,
}