update for lp_categories,
This commit is contained in:
@@ -1,44 +1,60 @@
|
||||
'use client';
|
||||
|
||||
/*
|
||||
# PROMPT
|
||||
|
||||
this is a subset of a typescript project
|
||||
|
||||
clone `LessonTypeCount`, `LessonCategoriesCount` to `UserCount` and do modifiy to get the count of users, thanks.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import getAllUserMetasCount from '@/db/UserMetas/GetAllCount';
|
||||
// import GetAllUsersCount from '@/db/Users/GetAllCount.tsx';
|
||||
import { Typography } from '@mui/material';
|
||||
import { Users as UsersIcon } from '@phosphor-icons/react/dist/ssr/Users';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Summary } from '@/components/dashboard/overview/summary';
|
||||
|
||||
import { LoadingSummary } from '../LoadingSummary';
|
||||
|
||||
function ActiveUserCount(): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const [amount, setAmount] = React.useState<number>(0);
|
||||
const [isLoading, setIsLoading] = React.useState<boolean>(true);
|
||||
const [showLoading, setShowLoading] = React.useState<boolean>(true);
|
||||
const [showError, setShowError] = React.useState<boolean>(false);
|
||||
const [errorDetail, setErrorDetail] = React.useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
getAllUserMetasCount()
|
||||
.then((count) => {
|
||||
setAmount(count);
|
||||
setIsLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
setAmount(-99);
|
||||
});
|
||||
async function count(): Promise<void> {
|
||||
try {
|
||||
const tempCount = await getAllUserMetasCount();
|
||||
setAmount(tempCount);
|
||||
} catch (error) {
|
||||
setAmount(-9);
|
||||
setErrorDetail(JSON.stringify(error));
|
||||
setShowError(true);
|
||||
} finally {
|
||||
setShowLoading(false);
|
||||
}
|
||||
}
|
||||
void count();
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <Typography>Loading...</Typography>;
|
||||
if (showLoading) {
|
||||
return <LoadingSummary diff={10} icon={UsersIcon} title={t('用戶數量')} trend="up" />;
|
||||
}
|
||||
|
||||
if (showError) return <div>{errorDetail}</div>;
|
||||
|
||||
return (
|
||||
<Summary
|
||||
amount={amount}
|
||||
diff={10}
|
||||
icon={UsersIcon}
|
||||
title={t('用戶數量1')}
|
||||
title={t('用戶數量')}
|
||||
trend="up"
|
||||
//
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default ActiveUserCount;
|
||||
export default React.memo(ActiveUserCount);
|
||||
|
@@ -8,35 +8,43 @@ this is a subset of a typescript project
|
||||
clone `LessonTypeCount`, `LessonCategoriesCount` to `UserCount` and do modifiy to get the count of users, thanks.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import GetAllCount from '@/db/LessonCategories/GetAllCount.tsx';
|
||||
import { Typography } from '@mui/material';
|
||||
import getAllLessonCategoriesCount from '@/db/LessonCategories/GetAllCount.tsx';
|
||||
import { ListChecks as ListChecksIcon } from '@phosphor-icons/react/dist/ssr/ListChecks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Summary } from '@/components/dashboard/overview/summary';
|
||||
|
||||
import { LoadingSummary } from '../LoadingSummary';
|
||||
|
||||
function LessonCategoriesCount(): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const [amount, setAmount] = React.useState<number>(0);
|
||||
const [isLoading, setIsLoading] = React.useState<boolean>(true);
|
||||
const [showLoading, setShowLoading] = React.useState<boolean>(true);
|
||||
const [showError, setShowError] = React.useState<boolean>(false);
|
||||
const [errorDetail, setErrorDetail] = React.useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
GetAllCount()
|
||||
.then((count) => {
|
||||
setAmount(count);
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.error(err);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
async function count(): Promise<void> {
|
||||
try {
|
||||
const tempCount = await getAllLessonCategoriesCount();
|
||||
setAmount(tempCount);
|
||||
} catch (error) {
|
||||
setAmount(-9);
|
||||
setErrorDetail(JSON.stringify(error));
|
||||
setShowError(true);
|
||||
} finally {
|
||||
setShowLoading(false);
|
||||
}
|
||||
}
|
||||
void count();
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <Typography>Loading</Typography>;
|
||||
if (showLoading) {
|
||||
return <LoadingSummary diff={10} icon={ListChecksIcon} title={t('用戶數量')} trend="up" />;
|
||||
}
|
||||
|
||||
if (showError) return <div>{errorDetail}</div>;
|
||||
|
||||
return (
|
||||
<Summary
|
||||
amount={amount}
|
||||
|
@@ -1,52 +1,43 @@
|
||||
'use client';
|
||||
|
||||
/*
|
||||
# PROMPT
|
||||
|
||||
this is a subset of a typescript project
|
||||
|
||||
clone `LessonTypeCount` to `LessonCategoriesCount` and do modifiy to get the count of lesson category, thanks.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import GetAllCount from '@/db/LessonTypes/GetAllCount.tsx';
|
||||
import { Typography } from '@mui/material';
|
||||
import { ListChecks as ListChecksIcon } from '@phosphor-icons/react/dist/ssr/ListChecks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { Summary } from '@/components/dashboard/overview/summary';
|
||||
import { LoadingSummary } from '@/components/dashboard/overview/summary/LoadingSummary';
|
||||
|
||||
function LessonTypeCount(): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const [amount, setAmount] = React.useState<number>(0);
|
||||
const [isLoading, setIsLoading] = React.useState<boolean>(true);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
GetAllCount()
|
||||
.then((count) => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const count = await GetAllCount();
|
||||
setAmount(count);
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.error(err);
|
||||
})
|
||||
.finally(() => {
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Unknown error');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void fetchData();
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
return <Typography>Loading...</Typography>;
|
||||
return <LoadingSummary />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Summary
|
||||
amount={amount}
|
||||
diff={15}
|
||||
icon={ListChecksIcon}
|
||||
title={t('課程類型')}
|
||||
trend="up"
|
||||
//
|
||||
/>
|
||||
);
|
||||
if (error) {
|
||||
return <Summary amount={0} diff={0} icon={ListChecksIcon} title={t('Error')} trend="down" />;
|
||||
}
|
||||
|
||||
return <Summary amount={amount} diff={15} icon={ListChecksIcon} title={t('課程類型')} trend="up" />;
|
||||
}
|
||||
|
||||
export default React.memo(LessonTypeCount);
|
||||
|
@@ -0,0 +1,81 @@
|
||||
'use client';
|
||||
|
||||
/*
|
||||
# PROMPT
|
||||
|
||||
this is a subset of a typescript project
|
||||
|
||||
clone `LessonTypeCount`, `LessonCategoriesCount` to `UserCount` and do modifiy to get the count of users, thanks.
|
||||
*/
|
||||
import * as React from 'react';
|
||||
import Avatar from '@mui/material/Avatar';
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import type { Icon } from '@phosphor-icons/react/dist/lib/types';
|
||||
import { TrendDown as TrendDownIcon } from '@phosphor-icons/react/dist/ssr/TrendDown';
|
||||
import { TrendUp as TrendUpIcon } from '@phosphor-icons/react/dist/ssr/TrendUp';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface SummaryProps {
|
||||
diff: number;
|
||||
icon: Icon;
|
||||
title: string;
|
||||
trend: 'up' | 'down';
|
||||
}
|
||||
|
||||
export function LoadingSummary({ diff, icon: Icon, title, trend }: SummaryProps): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Stack direction="row" spacing={3} sx={{ alignItems: 'center' }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
'--Avatar-size': '48px',
|
||||
bgcolor: 'var(--mui-palette-background-paper)',
|
||||
boxShadow: 'var(--mui-shadows-8)',
|
||||
color: 'var(--mui-palette-text-primary)',
|
||||
}}
|
||||
>
|
||||
<Icon fontSize="var(--icon-fontSize-lg)" />
|
||||
</Avatar>
|
||||
<div>
|
||||
<Typography color="text.secondary" variant="body1">
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="h3">Loading</Typography>
|
||||
</div>
|
||||
</Stack>
|
||||
</CardContent>
|
||||
<Divider />
|
||||
<Box sx={{ p: '16px' }}>
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
||||
<Box
|
||||
sx={{
|
||||
alignItems: 'center',
|
||||
color: trend === 'up' ? 'var(--mui-palette-success-main)' : 'var(--mui-palette-error-main)',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{trend === 'up' ? (
|
||||
<TrendUpIcon fontSize="var(--icon-fontSize-md)" />
|
||||
) : (
|
||||
<TrendDownIcon fontSize="var(--icon-fontSize-md)" />
|
||||
)}
|
||||
</Box>
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
<Typography color={trend === 'up' ? 'success.main' : 'error.main'} component="span" variant="subtitle2">
|
||||
{new Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 2 }).format(diff / 100)}
|
||||
</Typography>{' '}
|
||||
{trend === 'up' ? t('increase') : t('decrease')} {t('vs last month')}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user