import React, { useState, useMemo } from 'react'; import { FormattedMessage } from 'react-intl'; import { FixedSizeList } from 'react-window'; import { useSpring, animated, config } from 'react-spring'; import classNames from 'classnames'; import Link from 'components/common/Link'; import Loading from 'components/common/Loading'; import NoData from 'components/common/NoData'; import useFetch from 'hooks/useFetch'; import Arrow from 'assets/arrow-right.svg'; import { percentFilter } from 'lib/filters'; import { formatNumber, formatLongNumber } from 'lib/format'; import useDateRange from 'hooks/useDateRange'; import usePageQuery from 'hooks/usePageQuery'; import styles from './MetricsTable.module.css'; import ErrorMessage from '../common/ErrorMessage'; export default function MetricsTable({ websiteId, websiteDomain, token, title, metric, type, className, dataFilter, filterOptions, limit, renderLabel, onDataLoad = () => {}, }) { const [dateRange] = useDateRange(websiteId); const { startDate, endDate, modified } = dateRange; const { resolve, router, query: { url }, } = usePageQuery(); const { data, loading, error } = useFetch( `/api/website/${websiteId}/rankings`, { type, start_at: +startDate, end_at: +endDate, domain: websiteDomain, url, token, }, { onDataLoad, delay: 300, update: [modified] }, ); const [format, setFormat] = useState(true); const formatFunc = format ? formatLongNumber : formatNumber; const shouldAnimate = limit > 0; const rankings = useMemo(() => { if (data) { const items = percentFilter(dataFilter ? dataFilter(data, filterOptions) : data); if (limit) { return items.filter((e, i) => i < limit); } return items; } return []; }, [data, error, dataFilter, filterOptions]); const handleSetFormat = () => setFormat(state => !state); const getRow = row => { const { x: label, y: value, z: percent } = row; return ( ); }; const Row = ({ index, style }) => { return
{getRow(rankings[index])}
; }; return (
{!data && loading && } {error && } {data && !error && ( <>
{title}
{metric}
{rankings?.length === 0 && } {limit ? rankings.map(row => getRow(row)) : rankings.length > 0 && ( {Row} )}
{limit && ( } href={router.pathname} as={resolve({ view: type })} size="small" iconRight > )}
)}
); } const AnimatedRow = ({ label, value = 0, percent, animate, format, onClick }) => { const props = useSpring({ width: percent, y: value, from: { width: 0, y: 0 }, config: animate ? config.default : { duration: 0 }, }); return (
{label}
{props.y?.interpolate(format)}
`${n}%`) }} /> {props.width.interpolate(n => `${n.toFixed(0)}%`)}
); };