Merge pull request #6933 from thornbill/item-count-widget
Add item count widget to dashboard
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import type { Api } from '@jellyfin/sdk';
|
||||
import type { LibraryApiGetItemCountsRequest } from '@jellyfin/sdk/lib/generated-client/api/library-api';
|
||||
import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchItemCounts = async (
|
||||
api: Api,
|
||||
params?: LibraryApiGetItemCountsRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const response = await getLibraryApi(api)
|
||||
.getItemCounts(params, options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
const getItemCountsQuery = (
|
||||
api?: Api,
|
||||
params?: LibraryApiGetItemCountsRequest
|
||||
) => queryOptions({
|
||||
queryKey: [ 'ItemCounts', params ],
|
||||
queryFn: ({ signal }) => fetchItemCounts(api!, params, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
|
||||
export const useItemCounts = (
|
||||
params?: LibraryApiGetItemCountsRequest
|
||||
) => {
|
||||
const { api } = useApi();
|
||||
return useQuery(getItemCountsQuery(api, params));
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
import Skeleton from '@mui/material/Skeleton';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import SvgIcon from '@mui/material/SvgIcon';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import React, { type FC } from 'react';
|
||||
|
||||
import { useLocale } from 'hooks/useLocale';
|
||||
import { toDecimalString } from 'utils/number';
|
||||
|
||||
interface Metric {
|
||||
label: string
|
||||
value?: number
|
||||
}
|
||||
|
||||
interface MetricCardProps {
|
||||
metrics: Metric[]
|
||||
Icon: typeof SvgIcon
|
||||
}
|
||||
|
||||
const MetricCard: FC<MetricCardProps> = ({
|
||||
metrics,
|
||||
Icon
|
||||
}) => {
|
||||
const { dateTimeLocale } = useLocale();
|
||||
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
height: '100%'
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction='row'
|
||||
sx={{
|
||||
width: '100%',
|
||||
padding: 2,
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
{metrics.map(({ label, value }) => (
|
||||
<Box key={label}>
|
||||
<Typography
|
||||
variant='body2'
|
||||
color='text.secondary'
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant='h5'
|
||||
component='div'
|
||||
>
|
||||
{typeof value !== 'undefined' ? (
|
||||
toDecimalString(value, dateTimeLocale)
|
||||
) : (
|
||||
<Skeleton />
|
||||
)}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
<Icon fontSize='large' />
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default MetricCard;
|
||||
Reference in New Issue
Block a user