umami/src/app/(main)/reports/goals/GoalsChart.tsx

58 lines
2.1 KiB
TypeScript
Raw Normal View History

2024-05-06 05:15:47 +00:00
import { useContext } from 'react';
import classNames from 'classnames';
import { useMessages } from 'components/hooks';
import { ReportContext } from '../[reportId]/Report';
import { formatLongNumber } from 'lib/format';
import styles from './GoalsChart.module.css';
export function GoalsChart({ className }: { className?: string; isLoading?: boolean }) {
const { report } = useContext(ReportContext);
const { formatMessage, labels } = useMessages();
const { data } = report || {};
return (
<div className={classNames(styles.chart, className)}>
{data?.map(({ type, value, goal, result }, index: number) => {
2024-05-10 18:15:23 +00:00
const percent = result > goal ? 100 : (result / goal) * 100;
2024-05-06 05:15:47 +00:00
return (
2024-05-10 18:15:23 +00:00
<div key={index} className={styles.goal}>
2024-05-06 05:15:47 +00:00
<div className={styles.card}>
<div className={styles.header}>
<span className={styles.label}>
{formatMessage(type === 'url' ? labels.viewedPage : labels.triggeredEvent)}
</span>
<span className={styles.item}>{value}</span>
</div>
<div className={styles.track}>
2024-05-06 05:28:18 +00:00
<div
2024-05-10 18:15:23 +00:00
className={classNames(
classNames(styles.bar, {
[styles.level1]: percent <= 20,
[styles.level2]: percent > 20 && percent <= 40,
[styles.level3]: percent > 40 && percent <= 60,
[styles.level4]: percent > 60 && percent <= 80,
[styles.level5]: percent > 80,
}),
)}
style={{ width: `${percent}%` }}
2024-05-06 05:28:18 +00:00
></div>
2024-05-06 05:15:47 +00:00
</div>
2024-05-10 21:06:13 +00:00
<div className={styles.metric}>
<div className={styles.value}>
{formatLongNumber(result)}
<span className={styles.total}> / {formatLongNumber(goal)}</span>
</div>
<div className={styles.percent}>{((result / goal) * 100).toFixed(2)}%</div>
</div>
2024-05-06 05:15:47 +00:00
</div>
</div>
);
})}
</div>
);
}
export default GoalsChart;