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<{
29 label: string;
30 value: string | number | JSX.Element;
31}> = ({ label, value }) => (
32 <TableRow>
33 <TableCell>{label}</TableCell>
34 <TableCell>{value}</TableCell>
35 </TableRow>
36);
37
38const DateTableRow: FC<{ label: string; date: Date | string }> = ({
39 label,
40 date,
41}) => {
42 let formattedDate = "";
43 if (date && isValid(date)) {
44 formattedDate = format(date, "PPP");
45 }
46 return <TableRowWithCell label={label} value={formattedDate} />;
47};
48
49const CircularProgressBarRow: FC<{
50 label: string;
51 value: number;
52 limit: number;
53}> = ({ label, value, limit }) => (
54 <TableRow>
55 <TableCell>{label}</TableCell>
56 <TableCell>
57 <CircularProgress size="sm" value={(value / limit) * 100} />
58 </TableCell>
59 </TableRow>
60);
61
62export const UserInfoTable: FC<UserInfoTableProps> = ({ entity }) => {
63 const { t } = useTranslation();
64 const { mutate: resetUsage } = useUserUsageResetCmd();
65 const expireDate = entity.expire
66 ? isDate(entity.expire)
67 ? entity.expire
68 : new Date(entity.expire)
69 : null;
70
71 return (
72 <Card>
73 <CardHeader className="flex flex-row justify-between items-center w-full">
74 <CardTitle>{t("user_info")}</CardTitle>
75 </CardHeader>
76 <CardContent>
77 <Table>
78 <TableBody>
79 <TableRowWithCell label={t("username")} value={entity.username} />
80 <TableRowWithCell
81 label={t("status")}
82 value={<UsersStatusBadge status={UsersStatus[entity.status]} />}
83 />
84 {expireDate && entity.on_hold_expire_duration === 0 ? (
85 <DateTableRow
86 label={t("page.users.expire_date")}
87 date={expireDate}
88 />
89 ) : (
90 <>
91 <TableRowWithCell
92 label={t("page.users.on_hold_expire_duration")}
93 value={entity.on_hold_expire_duration}
94 />
95 {entity.on_hold_timeout && (
96 <DateTableRow
97 label={t("page.users.expire_date")}
98 date={entity.on_hold_timeout}
99 />
100 )}
101 </>
102 )}
103 {entity.data_limit && (
104 <CircularProgressBarRow
105 label={t("page.users.used_traffic")}
106 value={entity.used_traffic}
107 limit={entity.data_limit}
108 />
109 )}
110 <DateTableRow
111 label={t("page.users.online_at")}
112 date={entity.online_at}
113 />
114 <TableRowWithCell label={t("note")} value={entity.note} />
115 </TableBody>
116 </Table>
117 <div className="flex flex-row justify-center items-center gap-2">
118 <Button className="w-full" onClick={() => resetUsage(entity)}>
119 {t("page.users.reset_usage")}
120 </Button>
121 <UserStatusEnableButton user={entity} />
122 </div>
123 </CardContent>
124 </Card>
125 );
126};