mirror of
https://github.com/perfect-panel/ppanel-web.git
synced 2026-02-14 12:21:10 -05:00
- Added new keys for "server", "subscribe", "detail", "pending", "sending", "sent", and "unknown" in log.json files for various languages. - Introduced a "type" object with transaction types (Recharge, Withdraw, Purchase, Refund, Reward, Commission) in log.json files for multiple languages. - Updated "traffic_ratio" to "Ratio" and added "transport" in servers.json for English localization. - Ensured consistency and accuracy in translations for all affected languages including German, English, Spanish, French, Russian, Chinese, and more.
193 lines
6.9 KiB
TypeScript
193 lines
6.9 KiB
TypeScript
'use client';
|
|
|
|
import { Display } from '@/components/display';
|
|
import { getUserDetail, getUserSubscribeById } from '@/services/admin/user';
|
|
import { formatDate } from '@/utils/common';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { Button } from '@workspace/ui/components/button';
|
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@workspace/ui/components/hover-card';
|
|
import { formatBytes } from '@workspace/ui/utils';
|
|
import { useTranslations } from 'next-intl';
|
|
import Link from 'next/link';
|
|
|
|
export function UserSubscribeDetail({
|
|
id,
|
|
enabled,
|
|
hoverCard = false,
|
|
}: {
|
|
id: number;
|
|
enabled: boolean;
|
|
hoverCard?: boolean;
|
|
}) {
|
|
const t = useTranslations('user');
|
|
|
|
const { data } = useQuery({
|
|
enabled: id !== 0 && enabled,
|
|
queryKey: ['getUserSubscribeById', id],
|
|
queryFn: async () => {
|
|
const { data } = await getUserSubscribeById({ id });
|
|
return data.data;
|
|
},
|
|
});
|
|
|
|
if (!id) return '--';
|
|
|
|
const usedTraffic = data ? data.upload + data.download : 0;
|
|
const totalTraffic = data?.traffic || 0;
|
|
|
|
const subscribeContent = (
|
|
<div className='space-y-4'>
|
|
<div>
|
|
<h3 className='mb-2 text-sm font-medium'>{t('subscriptionInfo')}</h3>
|
|
<div className='bg-muted/30 rounded-lg p-3'>
|
|
<ul className='grid gap-3'>
|
|
<li className='flex items-center justify-between font-semibold'>
|
|
<span className='text-muted-foreground'>{t('subscriptionId')}</span>
|
|
<span>{data?.id || '--'}</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('subscriptionName')}</span>
|
|
<span>{data?.subscribe?.name || '--'}</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('token')}</span>
|
|
<div className='font-mono text-xs' title={data?.token || ''}>
|
|
{data?.token || '--'}
|
|
</div>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('trafficUsage')}</span>
|
|
<span>
|
|
{data
|
|
? totalTraffic === 0
|
|
? `${formatBytes(usedTraffic)} / ${t('unlimited')}`
|
|
: `${formatBytes(usedTraffic)} / ${formatBytes(totalTraffic)}`
|
|
: '--'}
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('startTime')}</span>
|
|
<span>{data?.start_time ? formatDate(data.start_time) : '--'}</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('expireTime')}</span>
|
|
<span>{data?.expire_time ? formatDate(data.expire_time) : '--'}</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
{!hoverCard && (
|
|
<div>
|
|
<h3 className='mb-2 text-sm font-medium'>
|
|
{t('userInfo')}
|
|
{/* Removed link to legacy user detail page */}
|
|
</h3>
|
|
<ul className='grid gap-3'>
|
|
<li className='flex items-center justify-between font-semibold'>
|
|
<span className='text-muted-foreground'>{t('userId')}</span>
|
|
<span>{data?.user_id}</span>
|
|
</li>
|
|
<li className='flex items-center justify-between font-semibold'>
|
|
<span className='text-muted-foreground'>{t('balance')}</span>
|
|
<span>
|
|
<Display type='currency' value={data?.user.balance} />
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('giftAmount')}</span>
|
|
<span>
|
|
<Display type='currency' value={data?.user?.gift_amount} />
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('commission')}</span>
|
|
<span>
|
|
<Display type='currency' value={data?.user?.commission} />
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('createdAt')}</span>
|
|
<span>{data?.user?.created_at && formatDate(data?.user?.created_at)}</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
|
|
if (hoverCard) {
|
|
return (
|
|
<HoverCard>
|
|
<HoverCardTrigger asChild>
|
|
<Button variant='link' className='p-0'>
|
|
{data?.subscribe?.name || t('loading')}
|
|
</Button>
|
|
</HoverCardTrigger>
|
|
<HoverCardContent className='w-96'>{subscribeContent}</HoverCardContent>
|
|
</HoverCard>
|
|
);
|
|
}
|
|
|
|
return subscribeContent;
|
|
}
|
|
|
|
export function UserDetail({ id }: { id: number }) {
|
|
const t = useTranslations('user');
|
|
|
|
const { data } = useQuery({
|
|
enabled: id !== 0,
|
|
queryKey: ['getUserDetail', id],
|
|
queryFn: async () => {
|
|
const { data } = await getUserDetail({ id });
|
|
return data.data;
|
|
},
|
|
});
|
|
|
|
if (!id) return '--';
|
|
|
|
return (
|
|
<HoverCard>
|
|
<HoverCardTrigger asChild>
|
|
<Button variant='link' className='p-0' asChild>
|
|
<Link href={`/dashboard/user?user_id=${id}`}>
|
|
{data?.auth_methods[0]?.auth_identifier || t('loading')}
|
|
</Link>
|
|
</Button>
|
|
</HoverCardTrigger>
|
|
<HoverCardContent>
|
|
<div className='grid gap-3'>
|
|
<ul className='grid gap-3'>
|
|
<li className='flex items-center justify-between font-semibold'>
|
|
<span className='text-muted-foreground'>ID</span>
|
|
<span>{data?.id}</span>
|
|
</li>
|
|
<li className='flex items-center justify-between font-semibold'>
|
|
<span className='text-muted-foreground'>{t('balance')}</span>
|
|
<span>
|
|
<Display type='currency' value={data?.balance} />
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('giftAmount')}</span>
|
|
<span>
|
|
<Display type='currency' value={data?.gift_amount} />
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('commission')}</span>
|
|
<span>
|
|
<Display type='currency' value={data?.commission} />
|
|
</span>
|
|
</li>
|
|
<li className='flex items-center justify-between'>
|
|
<span className='text-muted-foreground'>{t('createdAt')}</span>
|
|
<span>{data?.created_at && formatDate(data?.created_at)}</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</HoverCardContent>
|
|
</HoverCard>
|
|
);
|
|
}
|