gitscope
← marzneshin / v0.3.0-alpha9 / dashboard/src/features/users/dialogs/settings/user-info/table.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/features/users/dialogs/settings/user-info/table.tsx · TypeScript
Blame Raw
 1import {
 2    Button,
 3    Card,
 4    CardContent,
 5    CardHeader,
 6    CardTitle,
 7    Table,
 8    TableBody,
 9    TableCell,
10    TableRow
11} from "@marzneshin/components";
12import { FC } from 'react';
13import {
14    useUserUsageResetCmd,
15    UserType,
16    UsersStatus,
17    UsersStatusBadge,
18} from '@marzneshin/features/users';
19import { CircularProgress } from "@nextui-org/progress";
20import { useTranslation } from "react-i18next";
21import { format, isDate, isValid } from "date-fns";
22import { UserStatusEnableButton } from "./user-status-enable-button";
23
24interface UserInfoTableProps {
25    entity: UserType;
26}
27
28const TableRowWithCell: FC<{ label: string; value: string | number | JSX.Element }> = ({ label, value }) => (
29    <TableRow>
30        <TableCell>{label}</TableCell>
31        <TableCell>{value}</TableCell>
32    </TableRow>
33);
34
35const DateTableRow: FC<{ label: string; date: Date | string }> = ({ label, date }) => {
36    let formattedDate = '';
37    if (date && isValid(date)) {
38        formattedDate = format(date, "PPP");
39    }
40    return (
41        <TableRowWithCell label={label} value={formattedDate} />
42    );
43};
44
45const CircularProgressBarRow: FC<{ label: string; value: number; limit: number }> = ({ label, value, limit }) => (
46    <TableRow>
47        <TableCell>{label}</TableCell>
48        <TableCell><CircularProgress size="sm" value={value / limit * 100} /></TableCell>
49    </TableRow>
50);
51
52export const UserInfoTable: FC<UserInfoTableProps> = ({ entity }) => {
53    const { t } = useTranslation();
54    const { mutate: resetUsage } = useUserUsageResetCmd()
55    const expireDate = entity.expire ? (isDate(entity.expire) ? entity.expire : new Date(entity.expire)) : null;
56
57    return (
58        <Card>
59            <CardHeader className="flex flex-row justify-between items-center w-full">
60                <CardTitle>{t('user_info')}</CardTitle>
61                <div className="flex flex-row justify-center items-center gap-3">
62                    <Button onClick={() => resetUsage(entity)}>
63                        {t('page.users.reset_usage')}
64                    </Button>
65                    <UserStatusEnableButton user={entity} />
66                </div>
67            </CardHeader>
68            <CardContent>
69                <Table>
70                    <TableBody>
71                        <TableRowWithCell label={t('username')} value={entity.username} />
72                        <TableRowWithCell label={t('status')} value={<UsersStatusBadge status={UsersStatus[entity.status]} />} />
73                        {(expireDate && entity.on_hold_expire_duration === 0) ? (
74                            <DateTableRow label={t('page.users.expire_date')} date={expireDate} />
75                        ) : (
76                            <>
77                                <TableRowWithCell label={t('page.users.on_hold_expire_duration')} value={entity.on_hold_expire_duration} />
78                                {entity.on_hold_timeout &&
79                                    <DateTableRow label={t('page.users.expire_date')} date={entity.on_hold_timeout} />
80                                }
81                            </>
82                        )}
83                        {entity.data_limit &&
84                            <CircularProgressBarRow label={t('page.users.used_traffic')} value={entity.used_traffic} limit={entity.data_limit} />
85                        }
86                        <DateTableRow label={t('page.users.online_at')} date={entity.online_at} />
87                        <TableRowWithCell label={t('note')} value={entity.note} />
88                    </TableBody>
89                </Table>
90            </CardContent>
91        </Card>
92    );
93};