// Dependencies
import { linkClasses, formatNumber, orderBy, clone } from '@freesewing/utils'
// Hooks
import React, { useState, useEffect } from 'react'
import { useBackend } from '@freesewing/react/hooks/useBackend'
// Components
import { Spinner } from '@freesewing/react/components/Spinner'
import { Link as WebLink } from '@freesewing/react/components/Link'
import { ChartWrapper } from '@freesewing/react/components/Echart'
import { Popout } from '@freesewing/react/components/Popout'
const option = {
tooltip: {
trigger: 'axis',
show: true,
axisPointer: {
type: 'line',
lineStyle: {
type: 'dashed',
},
},
},
title: {
left: 'center',
},
grid: {
left: '40',
right: '60',
containLabel: true,
},
toolbox: {
feature: {
saveAsImage: {},
magicType: {
type: ['line', 'bar'],
},
},
},
yAxis: {
type: 'value',
},
}
/**
* A component to display generic stats from the FreeSewing backend
*
* @component
* @param {object} props - All component props
* @param {React.FC} [props.Link = false] - An optional framework-specific Link component
* @returns {JSX.Element}
*/
export const Stats = ({ Link = false }) => {
if (!Link) Link = WebLink
const [stats, setStats] = useState()
const [error, setError] = useState(false)
const backend = useBackend()
useEffect(() => {
getStats(backend, setStats, setError)
}, [])
if (!stats)
return (
)
const designTop = orderBy(
Object.entries(stats.designs).map(([design, count]) => ({ design, count })),
'count',
'desc'
).slice(0, 50)
const optionD = clone(option)
optionD.title.text = 'Top 50 FreeSewing Designs'
optionD.xAxis = {
type: 'category',
data: designTop.map((entry) => entry.design),
name: 'Design',
}
optionD.series = [
{
data: designTop.map((entry) => entry.count),
type: 'bar',
},
]
const optionU = clone(option)
optionU.title.text = 'Top 25 FreeSewing Users'
optionU.xAxis = {
type: 'category',
data: stats.topUsers.map((user) => user.username),
name: 'User',
}
optionU.series = [
{
data: stats.topUsers.map((user) => user.calls),
type: 'bar',
},
]
if (error)
return (
This is unexpected. You may want to report this.
)
return (
<>
Top Users
Note: Ordered by JWT calls made to the FreeSewing backend
{stats.topUsers.map((u) => (
-
{u.username}
: {formatNumber(u.calls)}
))}
Top Designs
Note: Ordered by patterns stored in the FreeSewing backend
{Object.entries(stats.designs).map(([d, c]) => (
-
{d}
: {formatNumber(c)}
))}
>
)
}
const Stat = ({ title, value, desc = 'Total Number Stored' }) => (
{title}
{formatNumber(value)}
{desc}
)
const getStats = async (backend, setStats, setError) => {
const result = await backend.getStats()
if (result[0] === 200 && result[1]) setStats(result[1])
else setError(true)
}