feat(subscription): Improve layout and organization of subscription detail tabs

This commit is contained in:
web@ppanel 2025-03-08 12:43:57 +07:00
parent 2215c7f2b9
commit e4630f8ca9

View File

@ -57,150 +57,154 @@ export function SubscriptionDetail({
{t('onlineDevices')} {t('onlineDevices')}
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
<TabsContent value='logs'> <div className='mt-4 max-h-[60dvh] overflow-y-auto'>
<ProTable<API.UserSubscribeLog, Record<string, unknown>> <TabsContent value='logs'>
columns={[ <ProTable<API.UserSubscribeLog, Record<string, unknown>>
{ columns={[
accessorKey: 'ip', {
header: 'IP', accessorKey: 'ip',
}, header: 'IP',
{ },
accessorKey: 'user_agent', {
header: t('userAgent'), accessorKey: 'user_agent',
}, header: t('userAgent'),
{ },
accessorKey: 'token', {
header: t('token'), accessorKey: 'token',
}, header: t('token'),
{ },
accessorKey: 'created_at', {
header: t('time'), accessorKey: 'created_at',
cell: ({ row }) => formatDate(row.getValue('created_at')), header: t('time'),
}, cell: ({ row }) => formatDate(row.getValue('created_at')),
]} },
request={async (pagination) => { ]}
const { data } = await getUserSubscribeLogs({ request={async (pagination) => {
user_id: userId, const { data } = await getUserSubscribeLogs({
subscribe_id: subscriptionId, user_id: userId,
...pagination, subscribe_id: subscriptionId,
}); ...pagination,
return { });
list: data.data?.list || [], return {
total: data.data?.total || 0, list: data.data?.list || [],
}; total: data.data?.total || 0,
}} };
/> }}
</TabsContent> />
<TabsContent value='traffic'> </TabsContent>
<ProTable<API.TrafficLog, Record<string, unknown>> <TabsContent value='traffic'>
columns={[ <ProTable<API.TrafficLog, Record<string, unknown>>
{ columns={[
accessorKey: 'download', {
header: t('download'), accessorKey: 'download',
cell: ({ row }) => <Display type='traffic' value={row.getValue('download')} />, header: t('download'),
}, cell: ({ row }) => (
{ <Display type='traffic' value={row.getValue('download')} />
accessorKey: 'upload', ),
header: t('upload'), },
cell: ({ row }) => <Display type='traffic' value={row.getValue('upload')} />, {
}, accessorKey: 'upload',
{ header: t('upload'),
accessorKey: 'timestamp', cell: ({ row }) => <Display type='traffic' value={row.getValue('upload')} />,
header: t('time'), },
cell: ({ row }) => formatDate(row.getValue('timestamp')), {
}, accessorKey: 'timestamp',
]} header: t('time'),
request={async (pagination) => { cell: ({ row }) => formatDate(row.getValue('timestamp')),
const { data } = await getUserSubscribeTrafficLogs({ },
user_id: userId, ]}
subscribe_id: subscriptionId, request={async (pagination) => {
...pagination, const { data } = await getUserSubscribeTrafficLogs({
} as API.GetUserSubscribeTrafficLogsParams); user_id: userId,
return { subscribe_id: subscriptionId,
list: data.data?.list || [], ...pagination,
total: data.data?.total || 0, } as API.GetUserSubscribeTrafficLogsParams);
}; return {
}} list: data.data?.list || [],
/> total: data.data?.total || 0,
</TabsContent> };
<TabsContent value='devices'> }}
<ProTable<API.UserDevice, Record<string, unknown>> />
columns={[ </TabsContent>
{ <TabsContent value='devices'>
accessorKey: 'enabled', <ProTable<API.UserDevice, Record<string, unknown>>
header: t('enable'), columns={[
cell: ({ row }) => ( {
<Switch accessorKey: 'enabled',
checked={row.getValue('enabled')} header: t('enable'),
onChange={(checked) => { cell: ({ row }) => (
console.log('Switch:', checked); <Switch
}} checked={row.getValue('enabled')}
/> onChange={(checked) => {
), console.log('Switch:', checked);
}, }}
{ />
accessorKey: 'id', ),
header: 'ID', },
}, {
{ accessorKey: 'id',
accessorKey: 'identifier', header: 'ID',
header: 'IMEI', },
}, {
{ accessorKey: 'identifier',
accessorKey: 'user_agent', header: 'IMEI',
header: t('userAgent'), },
}, {
{ accessorKey: 'user_agent',
accessorKey: 'ip', header: t('userAgent'),
header: 'IP', },
}, {
{ accessorKey: 'ip',
accessorKey: 'online', header: 'IP',
header: t('loginStatus'), },
cell: ({ row }) => ( {
<Badge variant={row.getValue('online') ? 'default' : 'destructive'}> accessorKey: 'online',
{row.getValue('online') ? t('online') : t('offline')} header: t('loginStatus'),
</Badge> cell: ({ row }) => (
), <Badge variant={row.getValue('online') ? 'default' : 'destructive'}>
}, {row.getValue('online') ? t('online') : t('offline')}
{ </Badge>
accessorKey: 'updated_at', ),
header: t('lastSeen'), },
cell: ({ row }) => formatDate(row.getValue('updated_at')), {
}, accessorKey: 'updated_at',
]} header: t('lastSeen'),
request={async (pagination) => { cell: ({ row }) => formatDate(row.getValue('updated_at')),
const { data } = await getUserSubscribeDevices({ },
user_id: userId, ]}
subscribe_id: subscriptionId, request={async (pagination) => {
...pagination, const { data } = await getUserSubscribeDevices({
}); user_id: userId,
return { subscribe_id: subscriptionId,
list: data.data?.list || [], ...pagination,
total: data.data?.total || 0, });
}; return {
}} list: data.data?.list || [],
actions={{ total: data.data?.total || 0,
render: (row) => { };
if (!row.identifier) return []; }}
return [ actions={{
<ConfirmButton render: (row) => {
key='offline' if (!row.identifier) return [];
trigger={<Button variant='destructive'>{t('confirmOffline')}</Button>} return [
title={t('confirmOffline')} <ConfirmButton
description={t('kickOfflineConfirm', { ip: row.ip })} key='offline'
onConfirm={async () => { trigger={<Button variant='destructive'>{t('confirmOffline')}</Button>}
await kickOfflineByUserDevice({ id: row.id }); title={t('confirmOffline')}
toast.success(t('kickOfflineSuccess')); description={t('kickOfflineConfirm', { ip: row.ip })}
}} onConfirm={async () => {
cancelText={t('cancel')} await kickOfflineByUserDevice({ id: row.id });
confirmText={t('confirm')} toast.success(t('kickOfflineSuccess'));
/>, }}
]; cancelText={t('cancel')}
}, confirmText={t('confirm')}
}} />,
/> ];
</TabsContent> },
}}
/>
</TabsContent>
</div>
</Tabs> </Tabs>
</div> </div>
</DialogContent> </DialogContent>