feat: 修改文案大小
This commit is contained in:
parent
9cde4cb0a1
commit
bf8c01048c
@ -5,7 +5,7 @@
|
|||||||
### 熟练部署命令
|
### 熟练部署命令
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
APP_NAME="ppanel-admin-web-dev"
|
APP_NAME="ppanel-admin-web"
|
||||||
tar -xzvf ${APP_NAME}.tar.gz && pm2 start ${APP_NAME} && pm2 list
|
tar -xzvf ${APP_NAME}.tar.gz && pm2 start ${APP_NAME} && pm2 list
|
||||||
unset APP_NAME # 显式销毁变量
|
unset APP_NAME # 显式销毁变量
|
||||||
```
|
```
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export function Header() {
|
|||||||
const items = useMemo(() => findNavByUrl(pathname), [pathname]);
|
const items = useMemo(() => findNavByUrl(pathname), [pathname]);
|
||||||
return (
|
return (
|
||||||
<header className='flex h-[84px] w-full items-center justify-end gap-2 px-4 pt-4 md:hidden'>
|
<header className='flex h-[84px] w-full items-center justify-end gap-2 px-4 pt-4 md:hidden'>
|
||||||
<SidebarTrigger className={'fixed left-4'} />
|
<SidebarTrigger className={'fixed left-4 z-50'} />
|
||||||
<Breadcrumb>
|
<Breadcrumb>
|
||||||
<BreadcrumbList className={'text-[36px] font-semibold'}>
|
<BreadcrumbList className={'text-[36px] font-semibold'}>
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
|
|||||||
@ -51,8 +51,8 @@ export const AnnouncementDialog = ({ ref }: AnnouncementDialogProps) => {
|
|||||||
const response = await queryAnnouncement({
|
const response = await queryAnnouncement({
|
||||||
...pagination,
|
...pagination,
|
||||||
...filter,
|
...filter,
|
||||||
pinned: false,
|
// pinned: false,
|
||||||
popup: false,
|
// popup: false,
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
list: response.data.data?.announcements || [],
|
list: response.data.data?.announcements || [],
|
||||||
@ -62,7 +62,7 @@ export const AnnouncementDialog = ({ ref }: AnnouncementDialogProps) => {
|
|||||||
renderItem={(item) => {
|
renderItem={(item) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-2 shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)]`}
|
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-1.5 shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)]`}
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
|
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Display } from '@/components/display';
|
import { Display } from '@/components/display';
|
||||||
import Renewal from '@/components/subscribe/renewal';
|
import Renewal from '@/components/subscribe/renewal';
|
||||||
import { resetUserSubscribeToken } from '@/services/user/user';
|
import { resetUserSubscribeToken } from '@/services/user/user';
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@ -14,6 +13,7 @@ import { toast } from 'sonner';
|
|||||||
|
|
||||||
import SvgIcon from '@/components/SvgIcon';
|
import SvgIcon from '@/components/SvgIcon';
|
||||||
import useGlobalStore from '@/config/use-global';
|
import useGlobalStore from '@/config/use-global';
|
||||||
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
@ -62,13 +62,13 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* 统计信息 */}
|
{/* 统计信息 */}
|
||||||
<div className='rounded-[20px] bg-[#EAEAEA] p-4'>
|
<div className='rounded-[20px] bg-[#EAEAEA] py-4'>
|
||||||
<div className='grid grid-cols-3 gap-4 text-center'>
|
<div className='grid grid-cols-3 gap-4 text-center'>
|
||||||
<div>
|
<div>
|
||||||
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-xs'>
|
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-sm'>
|
||||||
{t('totalTraffic')}
|
{t('totalTraffic')}
|
||||||
</p>
|
</p>
|
||||||
<p className='text-xs font-medium text-[#0F2C53] sm:text-lg'>
|
<p className='text-xs font-medium text-[#0F2C53] sm:text-base'>
|
||||||
<Display
|
<Display
|
||||||
type='traffic'
|
type='traffic'
|
||||||
value={userSubscribeData.traffic}
|
value={userSubscribeData.traffic}
|
||||||
@ -77,20 +77,20 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-xs'>
|
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-sm'>
|
||||||
{t('nextResetDays')}
|
{t('nextResetDays')}
|
||||||
</p>
|
</p>
|
||||||
<p className='text-xs font-medium text-[#0F2C53] sm:text-lg'>
|
<p className='text-xs font-medium text-[#0F2C53] sm:text-base'>
|
||||||
{userSubscribeData.reset_time
|
{userSubscribeData.reset_time
|
||||||
? differenceInDays(new Date(userSubscribeData.reset_time), new Date())
|
? differenceInDays(new Date(userSubscribeData.reset_time), new Date())
|
||||||
: t('noReset')}
|
: t('noReset')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-xs'>
|
<p className='text-[10px] text-[rgba(132,132,132,0.7)] sm:text-sm'>
|
||||||
{t('expirationDays')}
|
{t('expirationDays')}
|
||||||
</p>
|
</p>
|
||||||
<p className='text-xs font-medium text-[#0F2C53] sm:text-lg'>
|
<p className='text-xs font-medium text-[#0F2C53] sm:text-base'>
|
||||||
{userSubscribeData.expire_time
|
{userSubscribeData.expire_time
|
||||||
? differenceInDays(new Date(userSubscribeData.expire_time), new Date()) ||
|
? differenceInDays(new Date(userSubscribeData.expire_time), new Date()) ||
|
||||||
t('unknown')
|
t('unknown')
|
||||||
@ -123,7 +123,7 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={'mb-3 flex items-center justify-center gap-1'}>
|
<div className={'mb-3 flex items-center justify-center gap-3'}>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'flex flex-1 items-center gap-1 rounded-full bg-[#BABABA] pl-1 sm:gap-2 sm:rounded-[16px] sm:pl-2'
|
'flex flex-1 items-center gap-1 rounded-full bg-[#BABABA] pl-1 sm:gap-2 sm:rounded-[16px] sm:pl-2'
|
||||||
@ -133,14 +133,14 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
value={userSubscribeProtocolCurrent}
|
value={userSubscribeProtocolCurrent}
|
||||||
onValueChange={setUserSubscribeProtocolCurrent}
|
onValueChange={setUserSubscribeProtocolCurrent}
|
||||||
>
|
>
|
||||||
<SelectTrigger className='h-auto w-auto flex-shrink-0 rounded-[16px] border-none bg-[#D9D9D9] px-2.5 py-0.5 text-[13px] text-sm font-medium text-white shadow-none hover:bg-[#848484] focus:ring-0 sm:h-[35px] sm:rounded-[8px] sm:p-2 [&>svg]:hidden'>
|
<SelectTrigger className='h-auto w-auto flex-shrink-0 rounded-[16px] border-none bg-[#D9D9D9] px-2.5 py-0.5 text-[13px] font-medium text-[#0F2C53] shadow-none hover:bg-[#848484] focus:ring-0 sm:h-[35px] sm:rounded-[8px] sm:px-2 sm:py-1.5 [&>svg]:hidden'>
|
||||||
<SelectValue>
|
<SelectValue>
|
||||||
<div className='flex flex-col items-center justify-center text-[10px] sm:text-sm'>
|
<div className='flex flex-col items-center justify-between text-[10px] sm:text-xs'>
|
||||||
<div>
|
<div>
|
||||||
{t('subscriptionUrl')}
|
{t('subscriptionUrl')}
|
||||||
{userSubscribeProtocolCurrent + 1}
|
{userSubscribeProtocolCurrent + 1}
|
||||||
</div>
|
</div>
|
||||||
<div className='-mt-0.5 h-0 w-0 scale-50 border-l-[5px] border-r-[5px] border-t-[5px] border-l-transparent border-r-transparent border-t-white sm:scale-100'></div>
|
<div className='-mt-0.5 h-0 w-0 scale-50 border-l-[3px] border-r-[3px] border-t-[3px] border-l-transparent border-r-transparent border-t-[#0F2C53] sm:scale-100'></div>
|
||||||
</div>
|
</div>
|
||||||
</SelectValue>
|
</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
@ -158,8 +158,8 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
<div className='flex-1 rounded-full bg-white px-3 py-1 text-[10px] leading-tight text-[#225BA9] shadow-[inset_0px_0px_7.6px_0px_rgba(0,0,0,0.25)] sm:rounded-[16px] sm:text-xs'>
|
<div className='flex-1 rounded-full bg-white px-3 py-2 text-[10px] leading-tight text-[#225BA9] shadow-[inset_0px_0px_7.6px_0px_rgba(0,0,0,0.25)] sm:rounded-[16px]'>
|
||||||
<div className={'flex items-center gap-4 py-1 text-[10px] sm:text-[16px]'}>
|
<div className={'flex items-center gap-4 py-1'}>
|
||||||
<div className={'line-clamp-2 flex-1 break-all'}>
|
<div className={'line-clamp-2 flex-1 break-all'}>
|
||||||
{userSubscribeProtocol[userSubscribeProtocolCurrent]}
|
{userSubscribeProtocol[userSubscribeProtocolCurrent]}
|
||||||
</div>
|
</div>
|
||||||
@ -203,15 +203,9 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
<div className='flex justify-between gap-2'>
|
<div className='flex justify-between gap-2'>
|
||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialogTrigger asChild>
|
||||||
<Button
|
<AiroButton variant='danger' className={'px-2 text-xs'}>
|
||||||
size='sm'
|
|
||||||
className={
|
|
||||||
'h-fit rounded-full bg-[#E22C2E] px-3 py-1 text-[10px] text-white sm:h-9 sm:text-xs'
|
|
||||||
}
|
|
||||||
variant='destructive'
|
|
||||||
>
|
|
||||||
{t('resetSubscription')}
|
{t('resetSubscription')}
|
||||||
</Button>
|
</AiroButton>
|
||||||
</AlertDialogTrigger>
|
</AlertDialogTrigger>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
@ -235,7 +229,7 @@ const SubscribeCard = (props: SubscribeCardProps) => {
|
|||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
<Renewal
|
<Renewal
|
||||||
className='h-fit rounded-full bg-[#A8D4ED] px-3 py-1 text-[10px] text-white sm:h-9 sm:text-xs'
|
className='px-2 text-xs'
|
||||||
id={userSubscribeData.id}
|
id={userSubscribeData.id}
|
||||||
subscribe={userSubscribeData.subscribe}
|
subscribe={userSubscribeData.subscribe}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -64,9 +64,9 @@ export default function Content() {
|
|||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await queryAnnouncement({
|
const { data } = await queryAnnouncement({
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 4,
|
size: 5,
|
||||||
pinned: false,
|
// pinned: false,
|
||||||
popup: false,
|
// popup: false,
|
||||||
});
|
});
|
||||||
return data.data?.announcements || [];
|
return data.data?.announcements || [];
|
||||||
},
|
},
|
||||||
@ -96,7 +96,7 @@ export default function Content() {
|
|||||||
<div className={'grid grid-cols-1 gap-[10px] sm:gap-6 lg:grid-cols-2'}>
|
<div className={'grid grid-cols-1 gap-[10px] sm:gap-6 lg:grid-cols-2'}>
|
||||||
{/* 账户概况 Card */}
|
{/* 账户概况 Card */}
|
||||||
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
|
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
|
||||||
<div className='mb-1 sm:mb-4'>
|
<div className='mb-1'>
|
||||||
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
|
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
|
||||||
{t('accountOverview')}
|
{t('accountOverview')}
|
||||||
</h3>
|
</h3>
|
||||||
@ -105,8 +105,8 @@ export default function Content() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mb-3 sm:mb-6'>
|
<div className='mb-3 sm:mb-3.5'>
|
||||||
<span className='text-2xl font-medium text-[#091B33] sm:text-3xl'>
|
<span className='text-2xl font-medium text-[#091B33]'>
|
||||||
{userSubscribe?.length > 0 && userSubscribe[0]?.status === 1 && orderData
|
{userSubscribe?.length > 0 && userSubscribe[0]?.status === 1 && orderData
|
||||||
? orderData?.quantity === 1
|
? orderData?.quantity === 1
|
||||||
? t('annualMonthPlanUser')
|
? t('annualMonthPlanUser')
|
||||||
@ -115,7 +115,7 @@ export default function Content() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='rounded-[20px] bg-[#EAEAEA] px-4 py-[10px]'>
|
<div className='rounded-[20px] bg-[#EAEAEA] px-5 py-2.5'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<span className='text-sm font-light text-[#666666]'>{t('accountBalance')}</span>
|
<span className='text-sm font-light text-[#666666]'>{t('accountBalance')}</span>
|
||||||
<Recharge
|
<Recharge
|
||||||
@ -124,7 +124,7 @@ export default function Content() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='text-xl font-medium text-[#225BA9] sm:text-4xl'>
|
<div className='text-xl font-medium text-[#225BA9] sm:text-2xl'>
|
||||||
<Display type='currency' value={totalAssets} />
|
<Display type='currency' value={totalAssets} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -132,7 +132,7 @@ export default function Content() {
|
|||||||
|
|
||||||
{/* 套餐状态 Card */}
|
{/* 套餐状态 Card */}
|
||||||
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 text-[#666666] shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
|
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 text-[#666666] shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
|
||||||
<div className='mb-4'>
|
<div className=''>
|
||||||
<h3 className='flex items-center justify-between text-[#666666]'>
|
<h3 className='flex items-center justify-between text-[#666666]'>
|
||||||
<div className={'flex items-center justify-between'}>
|
<div className={'flex items-center justify-between'}>
|
||||||
<span className={'text-base font-medium sm:text-xl'}>{t('planStatus')}</span>
|
<span className={'text-base font-medium sm:text-xl'}>{t('planStatus')}</span>
|
||||||
@ -153,12 +153,12 @@ export default function Content() {
|
|||||||
</div>
|
</div>
|
||||||
{userSubscribe?.length ? (
|
{userSubscribe?.length ? (
|
||||||
<>
|
<>
|
||||||
<div className='mb-2 text-sm text-[#666666] sm:mb-[22px] sm:mt-1'>
|
<div className='mt-1 text-xs text-[#666666] sm:text-sm'>
|
||||||
{t('planExpirationTime')}
|
{t('planExpirationTime')}
|
||||||
{formatDate(userSubscribe?.[0]?.expire_time, false)}
|
{formatDate(userSubscribe?.[0]?.expire_time, false)}
|
||||||
</div>
|
</div>
|
||||||
<div className='mb-3 sm:mb-6'>
|
<div className='mb-3 sm:mb-5'>
|
||||||
<span className='text-2xl font-medium text-[#091B33] sm:text-3xl'>
|
<span className='text-2xl font-medium text-[#091B33]'>
|
||||||
{userSubscribe?.[0]?.subscribe.name}
|
{userSubscribe?.[0]?.subscribe.name}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -226,7 +226,7 @@ export default function Content() {
|
|||||||
</Card>
|
</Card>
|
||||||
{/* 网站公告 Card */}
|
{/* 网站公告 Card */}
|
||||||
<Card className='relative order-4 rounded-[20px] border border-[#EAEAEA] bg-gradient-to-b from-white to-[#EAEAEA] p-6 pb-0 sm:order-none'>
|
<Card className='relative order-4 rounded-[20px] border border-[#EAEAEA] bg-gradient-to-b from-white to-[#EAEAEA] p-6 pb-0 sm:order-none'>
|
||||||
<div className='mb-3 flex items-center justify-between sm:mb-4'>
|
<div className='mb-3 flex items-center justify-between sm:mb-1'>
|
||||||
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
|
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
|
||||||
{t('siteAnnouncements')}
|
{t('siteAnnouncements')}
|
||||||
</h3>
|
</h3>
|
||||||
@ -248,7 +248,7 @@ export default function Content() {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-2`}
|
className={`${item.pinned ? 'bg-[#B5C9E2]' : 'bg-white'} flex items-center rounded-[20px] px-4 py-1.5`}
|
||||||
>
|
>
|
||||||
<p
|
<p
|
||||||
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
|
className={`${item.pinned ? 'text-white' : 'text-[#4D4D4D]'} line-clamp-2 flex-1 text-[10px] sm:text-sm`}
|
||||||
@ -285,7 +285,7 @@ export default function Content() {
|
|||||||
|
|
||||||
{/* 我的订阅 Card */}
|
{/* 我的订阅 Card */}
|
||||||
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
|
<Card className='rounded-[20px] border border-[#D9D9D9] p-6 shadow-[0px_0px_52.6px_1px_rgba(15,44,83,0.05)]'>
|
||||||
<div className='flex items-center justify-between sm:mb-4'>
|
<div className='flex items-center justify-between'>
|
||||||
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
|
<h3 className='text-base font-medium text-[#666666] sm:text-xl'>
|
||||||
{t('mySubscription')}
|
{t('mySubscription')}
|
||||||
</h3>
|
</h3>
|
||||||
|
|||||||
@ -67,7 +67,7 @@ const OrderDetailDialog = forwardRef<OrderDetailDialogRef, OrderDetailDialogProp
|
|||||||
<div className={'sr-only'}>order detail</div>
|
<div className={'sr-only'}>order detail</div>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent className='sm:w-[675px]'>
|
<DialogContent className='sm:w-[675px]'>
|
||||||
<div className='text-4xl font-bold text-[#0F2C53] sm:mb-8 sm:text-center sm:text-4xl'>
|
<div className='text-2xl font-bold text-[#0F2C53] sm:mb-8 sm:text-center'>
|
||||||
{t('orderDetail')}
|
{t('orderDetail')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -77,7 +77,7 @@ export default function Page() {
|
|||||||
</AiroButton>
|
</AiroButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CardContent className='px-0 py-3 pb-0 text-sm sm:pb-6'>
|
<CardContent className='px-0 py-3 pb-0 text-sm'>
|
||||||
<ul className='grid grid-cols-2 gap-3 *:flex *:flex-col lg:grid-cols-4'>
|
<ul className='grid grid-cols-2 gap-3 *:flex *:flex-col lg:grid-cols-4'>
|
||||||
<li>
|
<li>
|
||||||
<span className='text-[#225BA9]'>{t('name')}</span>
|
<span className='text-[#225BA9]'>{t('name')}</span>
|
||||||
|
|||||||
@ -29,16 +29,12 @@ export default function Page() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<LoginDialogProvider>
|
<LoginDialogProvider>
|
||||||
<div
|
<div className={'hidden text-4xl font-bold text-[#0F2C53] sm:block md:mb-4 md:text-center'}>
|
||||||
className={
|
|
||||||
'hidden text-4xl font-bold text-[#0F2C53] sm:block md:mb-4 md:text-center md:text-5xl'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{t('title')}
|
{t('title')}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'mt-0 text-right text-lg font-bold text-[#666666] sm:mt-0 sm:text-center sm:font-medium'
|
'mt-0 text-right text-base font-bold text-[#666666] sm:mt-0 sm:text-center sm:font-medium'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t('description')}
|
{t('description')}
|
||||||
|
|||||||
@ -27,23 +27,23 @@ const Table: React.FC<{}> = () => {
|
|||||||
<CardContent className='px-0 py-3 text-[10px] sm:p-3 sm:text-sm'>
|
<CardContent className='px-0 py-3 text-[10px] sm:p-3 sm:text-sm'>
|
||||||
<ul className='grid grid-cols-4 gap-3 *:flex *:flex-col'>
|
<ul className='grid grid-cols-4 gap-3 *:flex *:flex-col'>
|
||||||
<li className='font-semibold'>
|
<li className='font-semibold'>
|
||||||
<span className='text-[#225BA9]'>{t('createdAt')}</span>
|
<span className='font-normal text-[#225BA9]'>{t('createdAt')}</span>
|
||||||
<time>{formatDate(item.created_at)}</time>
|
<time className={'text-base'}>{formatDate(item.created_at)}</time>
|
||||||
</li>
|
</li>
|
||||||
<li className='font-semibold'>
|
<li className='font-semibold'>
|
||||||
<span className='text-[#225BA9]'>{t('type.0')}</span>
|
<span className='font-normal text-[#225BA9]'>{t('type.0')}</span>
|
||||||
<span>{t(`type.${item.type}`)}</span>
|
<span className={'text-base'}>{t(`type.${item.type}`)}</span>
|
||||||
</li>
|
</li>
|
||||||
<li className='font-semibold'>
|
<li className='font-semibold'>
|
||||||
<span className='text-[#225BA9]'>{t('amount')}</span>
|
<span className='font-normal text-[#225BA9]'>{t('amount')}</span>
|
||||||
<span>
|
<span className={'text-base'}>
|
||||||
<Display type='currency' value={item.amount} />
|
<Display type='currency' value={item.amount} />
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className='font-semibold'>
|
<li className='font-semibold'>
|
||||||
<span className='text-[#225BA9]'>{t('balance')}</span>
|
<span className='font-normal text-[#225BA9]'>{t('balance')}</span>
|
||||||
<span>
|
<span className={'text-base'}>
|
||||||
<Display type='currency' value={item.balance} />
|
<Display type='currency' value={item.balance} />
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export default function Page() {
|
|||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<div>
|
<div>
|
||||||
<p className='text-sm font-light text-[#666]'>{t('totalAssets')}</p>
|
<p className='text-sm font-light text-[#666]'>{t('totalAssets')}</p>
|
||||||
<p className='text-2xl font-bold sm:text-[32px]'>
|
<p className='text-2xl font-bold'>
|
||||||
<Display type='currency' value={totalAssets} />
|
<Display type='currency' value={totalAssets} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -39,37 +39,33 @@ export default function Page() {
|
|||||||
</div>
|
</div>
|
||||||
<div className='grid grid-cols-2 gap-2 sm:grid-cols-2 sm:gap-6 md:grid-cols-4'>
|
<div className='grid grid-cols-2 gap-2 sm:grid-cols-2 sm:gap-6 md:grid-cols-4'>
|
||||||
<div className='col-span-2 rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md sm:col-span-1'>
|
<div className='col-span-2 rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md sm:col-span-1'>
|
||||||
<p className='text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
|
<p className='text-sm font-light text-[#666] opacity-80 sm:mb-3'>
|
||||||
{t('accountBalance')}
|
{t('accountBalance')}
|
||||||
</p>
|
</p>
|
||||||
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
|
<p className='text-xl font-medium text-[#225BA9]'>
|
||||||
<Display type='currency' value={user?.balance} />
|
<Display type='currency' value={user?.balance} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
|
<div className='rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
|
||||||
<p className='t text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
|
<p className='text-sm font-light text-[#666] opacity-80 sm:mb-3'>{t('giftAmount')}</p>
|
||||||
{t('giftAmount')}
|
<p className='text-xl font-medium text-[#225BA9]'>
|
||||||
</p>
|
|
||||||
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
|
|
||||||
<Display type='currency' value={user?.gift_amount} />
|
<Display type='currency' value={user?.gift_amount} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
|
<div className='rounded-[20px] bg-[#EAEAEA] p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
|
||||||
<p className='t text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
|
<p className='text-sm font-light text-[#666] opacity-80 sm:mb-3'>{t('commission')}</p>
|
||||||
{t('commission')}
|
<p className='text-xl font-medium text-[#225BA9]'>
|
||||||
</p>
|
|
||||||
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
|
|
||||||
<Display type='currency' value={user?.commission} />
|
<Display type='currency' value={user?.commission} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='col-span-2 rounded-[20px] border-2 border-[#D9D9D9] p-4 shadow-sm transition-all duration-300 hover:shadow-md sm:col-span-1'>
|
<div className='col-span-2 rounded-[20px] border-2 border-[#D9D9D9] p-4 shadow-sm transition-all duration-300 hover:shadow-md sm:col-span-1'>
|
||||||
<p className='mb-1 flex justify-between text-sm font-medium text-[#666] opacity-80 sm:mb-3'>
|
<p className='mb-1 flex justify-between text-sm font-light text-[#666] sm:mb-3'>
|
||||||
<span>{t('referralCode')}</span>
|
<span>{t('referralCode')}</span>
|
||||||
<Link href='/affiliate' className={'text-[#225BA9]'}>
|
<Link href='/affiliate' className={'text-[#225BA9]'}>
|
||||||
{t('referralDetails')}
|
{t('referralDetails')}
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<p className='flex justify-between text-base font-bold text-[#225BA9] sm:text-2xl'>
|
<p className='flex justify-between text-base font-medium text-[#225BA9]'>
|
||||||
<span> {user?.refer_code}</span>
|
<span> {user?.refer_code}</span>
|
||||||
<CopyToClipboard
|
<CopyToClipboard
|
||||||
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
||||||
|
|||||||
@ -66,7 +66,7 @@ const LoginDialog = forwardRef<LoginDialogRef>((props, ref) => {
|
|||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogContent className='rounded-0 h-full w-full px-12 py-[4.5rem] sm:h-auto sm:w-[496px] sm:!rounded-[50px]'>
|
<DialogContent className='rounded-0 h-full w-full px-12 py-[4.5rem] sm:h-auto sm:w-[496px] sm:!rounded-[50px]'>
|
||||||
<DialogTitle className='sr-only'>Login</DialogTitle>
|
<DialogTitle className='sr-only'>Login</DialogTitle>
|
||||||
<div className='min-h-[524px]'>
|
<div className=''>
|
||||||
<EmailAuthForm hide={hide} isRedirect={isRedirect} />
|
<EmailAuthForm hide={hide} isRedirect={isRedirect} />
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import useGlobalStore from '@/config/use-global';
|
import useGlobalStore from '@/config/use-global';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
import { Button } from '@workspace/airo-ui/components/button';
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
@ -55,7 +56,7 @@ export default function LoginForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={'pb-9 pt-16 text-4xl font-bold'}>账户验证</div>
|
<div className={'h-[84px] text-2xl font-bold leading-[84px]'}>账户验证</div>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={handleSubmit} className=''>
|
<form onSubmit={handleSubmit} className=''>
|
||||||
<FormField
|
<FormField
|
||||||
@ -65,9 +66,7 @@ export default function LoginForm({
|
|||||||
<FormItem className={'mb-5'}>
|
<FormItem className={'mb-5'}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Email'
|
placeholder='Email'
|
||||||
type='email'
|
type='email'
|
||||||
{...field}
|
{...field}
|
||||||
@ -84,9 +83,7 @@ export default function LoginForm({
|
|||||||
<FormItem className={'mb-2'}>
|
<FormItem className={'mb-2'}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Password'
|
placeholder='Password'
|
||||||
type='password'
|
type='password'
|
||||||
{...field}
|
{...field}
|
||||||
@ -133,14 +130,15 @@ export default function LoginForm({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mt-6 flex justify-center'>
|
<div className='mt-6 flex justify-center'>
|
||||||
<Button
|
<AiroButton
|
||||||
type='submit'
|
type='submit'
|
||||||
|
variant='default'
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className='h-[64px] w-[219px] rounded-full border-[#0F2C53] bg-[#0F2C53] text-2xl font-bold hover:bg-[#225BA9] hover:text-white'
|
className='h-auto min-w-[157px] py-2 text-lg font-medium'
|
||||||
>
|
>
|
||||||
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
|
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
|
||||||
{t('title')}
|
{t('title')}
|
||||||
</Button>
|
</AiroButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import useGlobalStore from '@/config/use-global';
|
import useGlobalStore from '@/config/use-global';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
import { Button } from '@workspace/airo-ui/components/button';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -93,7 +95,7 @@ export default function RegisterForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={'pb-9 text-4xl font-bold'}>注册账户</div>
|
<div className={'h-[84px] text-2xl font-bold leading-[84px]'}>注册账户</div>
|
||||||
|
|
||||||
{auth.register.stop_register ? (
|
{auth.register.stop_register ? (
|
||||||
<Markdown>{t('message')}</Markdown>
|
<Markdown>{t('message')}</Markdown>
|
||||||
@ -108,9 +110,7 @@ export default function RegisterForm({
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Enter your email...'
|
placeholder='Enter your email...'
|
||||||
type='email'
|
type='email'
|
||||||
{...field}
|
{...field}
|
||||||
@ -127,9 +127,7 @@ export default function RegisterForm({
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Enter your password...'
|
placeholder='Enter your password...'
|
||||||
type='password'
|
type='password'
|
||||||
{...field}
|
{...field}
|
||||||
@ -146,9 +144,7 @@ export default function RegisterForm({
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
placeholder='Enter password again...'
|
placeholder='Enter password again...'
|
||||||
type='password'
|
type='password'
|
||||||
@ -169,9 +165,7 @@ export default function RegisterForm({
|
|||||||
<div className='flex items-center gap-8'>
|
<div className='flex items-center gap-8'>
|
||||||
<Input
|
<Input
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] flex-1 rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Enter code...'
|
placeholder='Enter code...'
|
||||||
type='text'
|
type='text'
|
||||||
{...field}
|
{...field}
|
||||||
@ -198,9 +192,7 @@ export default function RegisterForm({
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
disabled={loading || !!localStorage.getItem('invite')}
|
disabled={loading || !!localStorage.getItem('invite')}
|
||||||
placeholder={t('invite')}
|
placeholder={t('invite')}
|
||||||
{...field}
|
{...field}
|
||||||
@ -242,14 +234,14 @@ export default function RegisterForm({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-6 flex justify-center'>
|
<div className='mt-6 flex justify-center'>
|
||||||
<Button
|
<AiroButton
|
||||||
type='submit'
|
type='submit'
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className='h-[64px] w-[219px] rounded-full border-[#0F2C53] bg-[#0F2C53] text-2xl font-bold hover:bg-[#225BA9] hover:text-white'
|
className='h-auto min-w-[157px] py-2 text-lg font-medium'
|
||||||
>
|
>
|
||||||
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
|
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
|
||||||
{t('title')}
|
{t('title')}
|
||||||
</Button>
|
</AiroButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import useGlobalStore from '@/config/use-global';
|
import useGlobalStore from '@/config/use-global';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
import { Button } from '@workspace/airo-ui/components/button';
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
@ -60,7 +61,7 @@ export default function ResetForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={'pb-9 pt-10 text-4xl font-bold'}>找回账户</div>
|
<div className={'h-[84px] text-2xl font-bold leading-[84px]'}>找回账户</div>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className='grid gap-5'>
|
<div className='grid gap-5'>
|
||||||
@ -71,9 +72,7 @@ export default function ResetForm({
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Enter your email...'
|
placeholder='Enter your email...'
|
||||||
type='email'
|
type='email'
|
||||||
{...field}
|
{...field}
|
||||||
@ -91,9 +90,7 @@ export default function ResetForm({
|
|||||||
<FormControl>
|
<FormControl>
|
||||||
<div className='flex items-center gap-8'>
|
<div className='flex items-center gap-8'>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] flex-1 rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
placeholder='Enter code...'
|
placeholder='Enter code...'
|
||||||
type='text'
|
type='text'
|
||||||
@ -120,9 +117,7 @@ export default function ResetForm({
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
className={
|
className={'h-[46px] rounded-full shadow-[inset_0_0_7.6px_0_#00000040]'}
|
||||||
'h-[60px] rounded-[20px] text-xl shadow-[inset_0_0_7.6px_0_#00000040]'
|
|
||||||
}
|
|
||||||
placeholder='Enter your new password...'
|
placeholder='Enter your new password...'
|
||||||
type='password'
|
type='password'
|
||||||
{...field}
|
{...field}
|
||||||
@ -162,14 +157,14 @@ export default function ResetForm({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-6 flex justify-center'>
|
<div className='mt-6 flex justify-center'>
|
||||||
<Button
|
<AiroButton
|
||||||
type='submit'
|
type='submit'
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className='h-[64px] w-[219px] rounded-full border-[#0F2C53] bg-[#0F2C53] text-2xl font-bold hover:bg-[#225BA9] hover:text-white'
|
className='h-auto min-w-[157px] py-2 text-lg font-medium'
|
||||||
>
|
>
|
||||||
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
|
{loading && <Icon icon='mdi:loading' className='animate-spin' />}
|
||||||
{t('title')}
|
{t('title')}
|
||||||
</Button>
|
</AiroButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export default function SendCode({ type, params }: SendCodeProps) {
|
|||||||
<Button
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
className={
|
className={
|
||||||
'h-[60px] w-[109px] rounded-full border-[#A8D4ED] bg-[#A8D4ED] text-xl hover:bg-[#225BA9] hover:text-white'
|
'h-[30px] w-[109px] rounded-full border-[#A8D4ED] bg-[#A8D4ED] text-base hover:bg-[#225BA9] hover:text-white'
|
||||||
}
|
}
|
||||||
onClick={handleSendCode}
|
onClick={handleSendCode}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<svg viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect width="40" height="40" rx="10" fill="#D9D9D9"/>
|
<rect width="40" height="40" rx="10" fill="#D9D9D9"/>
|
||||||
<rect x="1" y="1" width="38" height="38" rx="9" stroke="#848484" stroke-opacity="0.28" stroke-width="2"/>
|
<rect x="1" y="1" width="38" height="38" rx="9" stroke="#225BA9" stroke-width="2"/>
|
||||||
<g clip-path="url(#clip0_795_3268)">
|
<g clip-path="url(#clip0_795_3268)">
|
||||||
<path d="M8.75 8C8.3375 8 8 8.3375 8 8.75V17.75C8 18.1625 8.3375 18.5 8.75 18.5H17.75C18.1625 18.5 18.5 18.1625 18.5 17.75V8.75C18.5 8.3375 18.1625 8 17.75 8H8.75ZM22.25 8C21.8375 8 21.5 8.3375 21.5 8.75V17.75C21.5 18.1625 21.8375 18.5 22.25 18.5H31.25C31.6625 18.5 32 18.1625 32 17.75V8.75C32 8.3375 31.6625 8 31.25 8H22.25ZM9.5 9.5H17V17H9.5V9.5ZM23 9.5H30.5V17H23V9.5ZM11 11V15.5H15.5V11H11ZM24.5 11V15.5H29V11H24.5ZM8.75 21.5C8.3375 21.5 8 21.8375 8 22.25V31.25C8 31.6625 8.3375 32 8.75 32H17.75C18.1625 32 18.5 31.6625 18.5 31.25V22.25C18.5 21.8375 18.1625 21.5 17.75 21.5H8.75ZM22.25 21.5C21.8375 21.5 21.5 21.8375 21.5 22.25V26H23V23H26V21.5H22.25ZM28.25 21.5C27.8375 21.5 27.5 21.8375 27.5 22.25V26H29V23H32V21.5H28.25ZM9.5 23H17V30.5H9.5V23ZM11 24.5V29H15.5V24.5H11ZM24.5 26V27.5H23.75C23.3375 27.5 23 27.8375 23 28.25V32H24.5V29H26V32H27.5V28.25C27.5 27.8375 27.1625 27.5 26.75 27.5H26V26H24.5ZM30.5 26V32H32V26H30.5Z" fill="#848484"/>
|
<path d="M8.75 8C8.3375 8 8 8.3375 8 8.75V17.75C8 18.1625 8.3375 18.5 8.75 18.5H17.75C18.1625 18.5 18.5 18.1625 18.5 17.75V8.75C18.5 8.3375 18.1625 8 17.75 8H8.75ZM22.25 8C21.8375 8 21.5 8.3375 21.5 8.75V17.75C21.5 18.1625 21.8375 18.5 22.25 18.5H31.25C31.6625 18.5 32 18.1625 32 17.75V8.75C32 8.3375 31.6625 8 31.25 8H22.25ZM9.5 9.5H17V17H9.5V9.5ZM23 9.5H30.5V17H23V9.5ZM11 11V15.5H15.5V11H11ZM24.5 11V15.5H29V11H24.5ZM8.75 21.5C8.3375 21.5 8 21.8375 8 22.25V31.25C8 31.6625 8.3375 32 8.75 32H17.75C18.1625 32 18.5 31.6625 18.5 31.25V22.25C18.5 21.8375 18.1625 21.5 17.75 21.5H8.75ZM22.25 21.5C21.8375 21.5 21.5 21.8375 21.5 22.25V26H23V23H26V21.5H22.25ZM28.25 21.5C27.8375 21.5 27.5 21.8375 27.5 22.25V26H29V23H32V21.5H28.25ZM9.5 23H17V30.5H9.5V23ZM11 24.5V29H15.5V24.5H11ZM24.5 26V27.5H23.75C23.3375 27.5 23 27.8375 23 28.25V32H24.5V29H26V32H27.5V28.25C27.5 27.8375 27.1625 27.5 26.75 27.5H26V26H24.5ZM30.5 26V32H32V26H30.5Z" fill="#225BA9"/>
|
||||||
</g>
|
</g>
|
||||||
<defs>
|
<defs>
|
||||||
<clipPath id="clip0_795_3268">
|
<clipPath id="clip0_795_3268">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -26,11 +26,11 @@ export default function Header() {
|
|||||||
<>
|
<>
|
||||||
<header className='fixed top-10 z-50 w-full'>
|
<header className='fixed top-10 z-50 w-full'>
|
||||||
<div className={'container'}>
|
<div className={'container'}>
|
||||||
<div className='flex h-[60px] items-center justify-between rounded-[50px] bg-white pl-4 pr-1 sm:h-[73px] md:pl-7'>
|
<div className='flex h-[60px] items-center justify-between rounded-[50px] bg-white pl-4 pr-3 md:pl-6'>
|
||||||
<nav className='flex-col gap-6 font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6'>
|
<nav className='flex-col gap-6 font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6'>
|
||||||
{Logo}
|
{Logo}
|
||||||
</nav>
|
</nav>
|
||||||
<div className='flex h-full flex-1 items-center justify-end gap-2 py-1'>
|
<div className='flex h-full flex-1 items-center justify-end gap-2 py-2'>
|
||||||
<LanguageSwitch />
|
<LanguageSwitch />
|
||||||
{/*<ThemeSwitch />*/}
|
{/*<ThemeSwitch />*/}
|
||||||
<UserNav />
|
<UserNav />
|
||||||
@ -43,7 +43,7 @@ export default function Header() {
|
|||||||
size: 'lg',
|
size: 'lg',
|
||||||
variant: 'outline',
|
variant: 'outline',
|
||||||
}),
|
}),
|
||||||
'h-full rounded-[50px] border-0 border-[#0F2C53] bg-[#0F2C53] px-5 text-[16px] font-bold text-white transition hover:bg-[#225BA9] hover:text-white sm:px-14 sm:text-2xl',
|
'h-full rounded-[50px] border-0 border-[#0F2C53] bg-[#0F2C53] px-5 text-base font-bold text-white transition hover:bg-[#225BA9] hover:text-white sm:px-10 sm:text-lg',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{t('login')}
|
{t('login')}
|
||||||
|
|||||||
@ -65,9 +65,7 @@ const PriceDisplay: React.FC<PriceDisplayProps> = ({ plan }) => {
|
|||||||
{common?.currency?.currency_symbol}
|
{common?.currency?.currency_symbol}
|
||||||
{plan.discount_price}
|
{plan.discount_price}
|
||||||
</span>
|
</span>
|
||||||
<span className='text-sm font-normal leading-[1.8em] text-[#4D4D4D] sm:text-[15px]'>
|
<span className='text-sm font-normal text-[#4D4D4D] sm:text-base'>{t('perYear')}</span>
|
||||||
{t('perYear')}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={'h-[15px]'}>
|
<div className={'h-[15px]'}>
|
||||||
{plan.origin_price && (
|
{plan.origin_price && (
|
||||||
@ -86,12 +84,13 @@ import Modal, { AlertDialogRef } from '@/components/Modal';
|
|||||||
import Purchase from '@/components/subscribe/purchase';
|
import Purchase from '@/components/subscribe/purchase';
|
||||||
import useGlobalStore from '@/config/use-global';
|
import useGlobalStore from '@/config/use-global';
|
||||||
import { queryUserSubscribe } from '@/services/user/user';
|
import { queryUserSubscribe } from '@/services/user/user';
|
||||||
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
// 星级评分组件
|
// 星级评分组件
|
||||||
const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: number }) => (
|
const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: number }) => (
|
||||||
<div className='text-right text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
|
<div className='text-right text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
|
||||||
{Array.from({ length: Math.min(rating, maxRating) }, (_, i) => (
|
{Array.from({ length: Math.min(rating, maxRating) }, (_, i) => (
|
||||||
<span key={i} className='text-black'>
|
<span key={i} className='text-black'>
|
||||||
✭
|
✭
|
||||||
@ -103,13 +102,13 @@ const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: num
|
|||||||
// 功能列表组件
|
// 功能列表组件
|
||||||
const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
|
const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
|
||||||
const t = useTranslations('subscribe.detail');
|
const t = useTranslations('subscribe.detail');
|
||||||
|
const tSubscribe = useTranslations('subscribe');
|
||||||
const tOffer = useTranslations('components.offerDialog');
|
const tOffer = useTranslations('components.offerDialog');
|
||||||
const features = [{ label: tOffer('availableNodes'), value: plan?.server_count }];
|
const features = [{ label: tOffer('availableNodes'), value: plan?.server_count }];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-6 space-y-0 sm:mt-6'>
|
<div className='mt-6 space-y-0 sm:mt-6'>
|
||||||
<ul className='list-disc space-y-1 pl-5'>
|
<ul className='list-disc space-y-0 pl-5'>
|
||||||
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
|
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
|
||||||
<div className={'flex items-start justify-between'}>
|
<div className={'flex items-start justify-between'}>
|
||||||
<span className=''>{t('availableTraffic')}</span>
|
<span className=''>{t('availableTraffic')}</span>
|
||||||
<span>
|
<span>
|
||||||
@ -117,7 +116,16 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
|
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
|
||||||
|
<div className={'flex items-start justify-between'}>
|
||||||
|
<span className=''>{tSubscribe('billing.duration')}</span>
|
||||||
|
<span>
|
||||||
|
{plan.origin_price ? '365' : '30'}
|
||||||
|
{tSubscribe('Day')}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
|
||||||
<div className={'flex items-start justify-between'}>
|
<div className={'flex items-start justify-between'}>
|
||||||
<span className=''>{t('connectionSpeed')}</span>
|
<span className=''>{t('connectionSpeed')}</span>
|
||||||
<span>
|
<span>
|
||||||
@ -125,7 +133,7 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
|
<li className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
|
||||||
<div className={'flex items-start justify-between'}>
|
<div className={'flex items-start justify-between'}>
|
||||||
<span className=''>{t('connectedDevices')}</span>
|
<span className=''>{t('connectedDevices')}</span>
|
||||||
<span>
|
<span>
|
||||||
@ -136,7 +144,7 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
|
|||||||
{features.map((feature) => (
|
{features.map((feature) => (
|
||||||
<li
|
<li
|
||||||
key={feature.label}
|
key={feature.label}
|
||||||
className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'
|
className='py-1 text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'
|
||||||
>
|
>
|
||||||
<div className={'flex items-start justify-between'}>
|
<div className={'flex items-start justify-between'}>
|
||||||
<span className=''>{feature.label}:</span>
|
<span className=''>{feature.label}:</span>
|
||||||
@ -146,7 +154,7 @@ const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
|
|||||||
))}
|
))}
|
||||||
<li className='py-1'>
|
<li className='py-1'>
|
||||||
<div className={'flex items-start justify-between'}>
|
<div className={'flex items-start justify-between'}>
|
||||||
<span className='text-xs font-light leading-[1.8461538461538463em] text-black sm:text-[13px]'>
|
<span className='text-xs font-light leading-[1.8461538461538463em] text-black sm:text-sm'>
|
||||||
{tOffer('networkStabilityIndex')}
|
{tOffer('networkStabilityIndex')}
|
||||||
</span>
|
</span>
|
||||||
<StarRating rating={5} />
|
<StarRating rating={5} />
|
||||||
@ -186,23 +194,24 @@ const PlanCard: React.FC<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative w-full min-w-[300px] cursor-pointer rounded-[20px] border border-[#D9D9D9] bg-white p-8 shadow-[0_0_52.6px_1px_rgba(15,44,83,0.05)] transition-all duration-300 sm:w-[345px] sm:p-10'>
|
<div className='relative w-full min-w-[300px] cursor-pointer rounded-[20px] border border-[#D9D9D9] bg-white p-8 shadow-[0_0_52.6px_1px_rgba(15,44,83,0.05)] transition-all duration-300 sm:w-[345px]'>
|
||||||
{/* 套餐名称 */}
|
<div className={'ml-4'}>
|
||||||
<h3 className='mb-4 text-left text-xl font-normal sm:mb-6 sm:text-base'>{plan.name}</h3>
|
{/* 套餐名称 */}
|
||||||
|
<h3 className='mb-3 text-left text-xl font-normal sm:text-base'>{plan.name}</h3>
|
||||||
|
|
||||||
{/* 价格区域 */}
|
{/* 价格区域 */}
|
||||||
<PriceDisplay plan={plan} />
|
<PriceDisplay plan={plan} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* 订阅按钮 */}
|
{/* 订阅按钮 */}
|
||||||
<button
|
<AiroButton onClick={handleSubscribe} className='h-10 w-full text-sm font-medium'>
|
||||||
onClick={handleSubscribe}
|
|
||||||
className='h-10 w-full rounded-full bg-[#0F2C53] text-sm font-medium text-white shadow-md transition-all duration-300 hover:bg-[#225BA9] sm:h-10 sm:text-sm md:h-[40px] md:text-[14px]'
|
|
||||||
>
|
|
||||||
{t('subscribe')}
|
{t('subscribe')}
|
||||||
</button>
|
</AiroButton>
|
||||||
|
|
||||||
{/* 功能列表 */}
|
<div className={'mx-4'}>
|
||||||
<FeatureList plan={plan} />
|
{/* 功能列表 */}
|
||||||
|
<FeatureList plan={plan} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
ref={ModalRef}
|
ref={ModalRef}
|
||||||
|
|||||||
@ -28,13 +28,13 @@ const PlanTabs: React.FC<PlanTabProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue='year'
|
defaultValue='year'
|
||||||
className={cn('mt-8 w-full text-center md:mt-16', className)}
|
className={cn('mt-8 w-full text-center md:mt-8', className)}
|
||||||
value={tabValue}
|
value={tabValue}
|
||||||
onValueChange={(value) => props.setTabValue(value as 'year' | 'month')}
|
onValueChange={(value) => props.setTabValue(value as 'year' | 'month')}
|
||||||
>
|
>
|
||||||
<TabsList className='relative mb-8 grid h-[74px] grid-cols-2 flex-wrap rounded-full bg-[#EAEAEA] p-2.5 md:mb-16'>
|
<TabsList className='relative mb-8 grid h-auto grid-cols-2 flex-wrap rounded-full bg-[#EAEAEA] px-2.5 py-2'>
|
||||||
{tabValue === 'year' ? (
|
{tabValue === 'year' ? (
|
||||||
<span className='absolute -top-8 left-16 z-10 rounded-sm bg-[#E22C2E] px-2 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
|
<span className='absolute -top-7 left-16 z-10 rounded-sm bg-[#E22C2E] px-3 py-0.5 text-[10px] font-bold leading-none text-white shadow sm:text-xs'>
|
||||||
-{props.discount}%{/* 小三角箭头 */}
|
-{props.discount}%{/* 小三角箭头 */}
|
||||||
<span
|
<span
|
||||||
className='absolute right-0 top-[75%] h-10 w-2 bg-[#E22C2E]'
|
className='absolute right-0 top-[75%] h-10 w-2 bg-[#E22C2E]'
|
||||||
@ -46,7 +46,7 @@ const PlanTabs: React.FC<PlanTabProps> = (props) => {
|
|||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
key={val.value}
|
key={val.value}
|
||||||
className={
|
className={
|
||||||
'rounded-full py-3.5 text-xl data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
'rounded-full py-2 text-base text-[#0F2C53] data-[state=active]:bg-[#0F2C53] data-[state=active]:text-white md:px-12'
|
||||||
}
|
}
|
||||||
value={val.value}
|
value={val.value}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -57,11 +57,11 @@ export const AffiliateDialog = ({ ref }: AffiliateDialogProps) => {
|
|||||||
return (
|
return (
|
||||||
<div className='flex flex-wrap justify-between gap-2 rounded-[20px] bg-white px-6 py-2 text-[10px] shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)] sm:text-base'>
|
<div className='flex flex-wrap justify-between gap-2 rounded-[20px] bg-white px-6 py-2 text-[10px] shadow-[0_0_4.5px_0_rgba(0,0,0,0.25)] sm:text-base'>
|
||||||
<div>
|
<div>
|
||||||
<div className={'text-[#225BA9]'}>{t('userIdentifier')}</div>
|
<div className={'text-sm text-[#225BA9]'}>{t('userIdentifier')}</div>
|
||||||
<div className={'font-bold text-[#091B33]'}>{invite.identifier}</div>
|
<div className={'font-bold text-[#091B33]'}>{invite.identifier}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className={'text-[#225BA9]'}>{t('time')}</div>
|
<div className={'text-sm text-[#225BA9]'}>{t('time')}</div>
|
||||||
<div className={'font-bold text-[#091B33]'}>
|
<div className={'font-bold text-[#091B33]'}>
|
||||||
{formatDate(invite.registered_at)}
|
{formatDate(invite.registered_at)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -66,24 +66,22 @@ export default function Affiliate() {
|
|||||||
<div className={'text-xs font-light sm:text-[15px]'}>{t('commissionInfo')}</div>
|
<div className={'text-xs font-light sm:text-[15px]'}>{t('commissionInfo')}</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={
|
className={'mb-3 text-xl font-bold leading-tight text-[#091B33] sm:mb-4 sm:text-2xl'}
|
||||||
'mb-3 text-xl font-bold leading-tight text-[#091B33] sm:text-[32px] sm:leading-[1.5]'
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{t('historicalRecommendedUsers')}
|
{t('historicalRecommendedUsers')}
|
||||||
{inviteListData?.total}
|
{inviteListData?.total}
|
||||||
</div>
|
</div>
|
||||||
<div className={'grid grid-cols-2 gap-[10px] sm:grid-cols-1 sm:gap-5 lg:grid-cols-2'}>
|
<div className={'grid grid-cols-2 gap-[10px] sm:grid-cols-1 sm:gap-5 lg:grid-cols-2'}>
|
||||||
<div className='rounded-[20px] border-2 border-[#EAEAEA] bg-[#EAEAEA] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:py-4'>
|
<div className='rounded-[20px] border-2 border-[#EAEAEA] bg-[#EAEAEA] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:px-5 sm:pb-2 sm:pt-4'>
|
||||||
<p className='flex justify-between font-medium text-[#666] opacity-80 sm:mb-3 sm:text-sm'>
|
<p className='flex justify-between font-light text-[#666] sm:mb-3 sm:text-sm'>
|
||||||
{t('totalCommission')}
|
{t('totalCommission')}
|
||||||
</p>
|
</p>
|
||||||
<p className='text-xl font-bold text-[#225BA9] sm:text-2xl'>
|
<p className='text-xl font-semibold text-[#225BA9]'>
|
||||||
<Display type='currency' value={data?.total_commission} />
|
<Display type='currency' value={data?.total_commission} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='rounded-[20px] border-2 border-[#D9D9D9] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:py-4'>
|
<div className='rounded-[20px] border-2 border-[#D9D9D9] px-4 py-2 shadow-sm transition-all duration-300 hover:shadow-md sm:px-5 sm:pb-2 sm:pt-4'>
|
||||||
<p className='flex justify-between font-medium text-[#666] opacity-80 sm:mb-3 sm:text-sm'>
|
<p className='flex justify-between font-light text-[#666] sm:mb-3 sm:text-sm'>
|
||||||
{t('commissionInviteCode')}
|
{t('commissionInviteCode')}
|
||||||
<CopyToClipboard
|
<CopyToClipboard
|
||||||
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
||||||
@ -102,7 +100,7 @@ export default function Affiliate() {
|
|||||||
</Button>
|
</Button>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</p>
|
</p>
|
||||||
<p className='flex justify-between text-xl font-bold text-[#225BA9] sm:text-2xl'>
|
<p className='flex justify-between text-xl font-bold text-[#225BA9]'>
|
||||||
<span> {user?.refer_code}</span>
|
<span> {user?.refer_code}</span>
|
||||||
<CopyToClipboard
|
<CopyToClipboard
|
||||||
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
||||||
@ -148,11 +146,11 @@ export default function Affiliate() {
|
|||||||
return (
|
return (
|
||||||
<div className='flex flex-wrap justify-between gap-2 rounded-[20px] bg-white px-6 py-2 text-[10px] sm:text-base'>
|
<div className='flex flex-wrap justify-between gap-2 rounded-[20px] bg-white px-6 py-2 text-[10px] sm:text-base'>
|
||||||
<div>
|
<div>
|
||||||
<div className={'text-[#225BA9]'}>{t('userIdentifier')}</div>
|
<div className={'text-sm text-[#225BA9]'}>{t('userIdentifier')}</div>
|
||||||
<div className={'font-bold text-[#091B33]'}>{invite.identifier}</div>
|
<div className={'font-bold text-[#091B33]'}>{invite.identifier}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className={'text-[#225BA9]'}>{t('time')}</div>
|
<div className={'text-sm text-[#225BA9]'}>{t('time')}</div>
|
||||||
<div className={'font-bold text-[#091B33]'}>
|
<div className={'font-bold text-[#091B33]'}>
|
||||||
{formatDate(invite.registered_at)}
|
{formatDate(invite.registered_at)}
|
||||||
</div>
|
</div>
|
||||||
@ -172,7 +170,9 @@ export default function Affiliate() {
|
|||||||
{t('commissionCalculation')}
|
{t('commissionCalculation')}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className={'mb-4 text-[10px] font-light text-[#0F2C53] sm:text-base'}>
|
<div
|
||||||
|
className={'mb-4 whitespace-pre-line text-[10px] font-light text-[#0F2C53] sm:text-sm'}
|
||||||
|
>
|
||||||
{t('commissionCalculationInfo')}
|
{t('commissionCalculationInfo')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export default function FooterCopyright() {
|
|||||||
const t = useTranslations('auth');
|
const t = useTranslations('auth');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={'fixed bottom-6 z-50 w-full text-xs sm:text-lg'}>
|
<footer className={'fixed bottom-6 z-[1] w-full text-xs sm:text-sm'}>
|
||||||
<div className={'container relative flex items-center justify-center text-right sm:block'}>
|
<div className={'container relative flex items-center justify-center text-right sm:block'}>
|
||||||
<Image
|
<Image
|
||||||
src={'./logo.png'}
|
src={'./logo.png'}
|
||||||
|
|||||||
@ -1,18 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { useRef } from 'react';
|
import OfferDialog from './OfferDialog/index';
|
||||||
import OfferDialog, { OfferDialogRef } from './OfferDialog/index';
|
|
||||||
|
|
||||||
export default function HomeContent() {
|
export default function HomeContent() {
|
||||||
const dialogRef = useRef<OfferDialogRef>(null);
|
|
||||||
const t = useTranslations('components.home');
|
const t = useTranslations('components.home');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex min-h-[calc(100vh-73px)] flex-col items-center justify-center pt-8'>
|
<div className='flex min-h-[calc(100vh-73px)] flex-col items-center justify-center pt-8'>
|
||||||
{/* 大标题 */}
|
{/* 大标题 */}
|
||||||
<h1 className='mb-6 self-start text-4xl font-bold !leading-tight text-white sm:mb-10 sm:self-center sm:text-6xl'>
|
<h1 className='mb-6 self-start text-4xl font-bold !leading-tight text-white sm:mb-10 sm:self-center sm:text-6xl sm:text-[64px]'>
|
||||||
{t('connect')}
|
{t('connect')}
|
||||||
<br />
|
<br />
|
||||||
{t('anytime')}
|
{t('anytime')}
|
||||||
@ -30,14 +27,7 @@ export default function HomeContent() {
|
|||||||
<p className={'mt-1 w-[255px] sm:mt-0 sm:w-full'}>{t('getSubscription')}</p>
|
<p className={'mt-1 w-[255px] sm:mt-0 sm:w-full'}>{t('getSubscription')}</p>
|
||||||
</div>
|
</div>
|
||||||
{/* 按钮 */}
|
{/* 按钮 */}
|
||||||
<Button
|
<OfferDialog />
|
||||||
onClick={() => dialogRef.current?.show()}
|
|
||||||
className='mb-8 h-auto rounded-full border-2 border-white bg-white/10 px-8 py-2 text-lg font-bold text-white transition hover:bg-white/25 sm:py-4 sm:text-2xl'
|
|
||||||
>
|
|
||||||
{t('viewSubscriptionPlans')}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<OfferDialog ref={dialogRef} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,22 @@
|
|||||||
import { getSubscription } from '@/services/user/portal';
|
import { getSubscription } from '@/services/user/portal';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { Dialog, DialogContent, DialogTitle } from '@workspace/airo-ui/components/dialog';
|
import {
|
||||||
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from '@workspace/airo-ui/components/dialog';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
import TabContent from '@/components/SubscribePlan/PlanContent/index';
|
import TabContent from '@/components/SubscribePlan/PlanContent/index';
|
||||||
import PlanTabs from '@/components/SubscribePlan/PlanTabs/PlanTabs';
|
import PlanTabs from '@/components/SubscribePlan/PlanTabs/PlanTabs';
|
||||||
|
import { Button } from '@workspace/airo-ui/components/button';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
|
|
||||||
export interface OfferDialogRef {
|
const OfferDialog = () => {
|
||||||
show: () => void;
|
|
||||||
hide: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
|
|
||||||
const t = useTranslations('components.offerDialog');
|
const t = useTranslations('components.offerDialog');
|
||||||
|
const tHome = useTranslations('components.home');
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [tabValue, setTabValue] = useState<'year' | 'month'>('year');
|
const [tabValue, setTabValue] = useState<'year' | 'month'>('year');
|
||||||
const dialogRef = useRef<HTMLDivElement>(null);
|
const dialogRef = useRef<HTMLDivElement>(null);
|
||||||
@ -40,28 +43,26 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
|
|||||||
},
|
},
|
||||||
enabled: true, // 初始不执行,手动控制
|
enabled: true, // 初始不执行,手动控制
|
||||||
retry: 1, // 失败时重试1次
|
retry: 1, // 失败时重试1次
|
||||||
|
refetchOnWindowFocus: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
|
||||||
show: () => {
|
|
||||||
refetch();
|
|
||||||
setOpen(true);
|
|
||||||
},
|
|
||||||
hide: () => setOpen(false),
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button className='mb-8 h-auto rounded-full border-[3px] border-white bg-white/10 px-8 py-2 text-lg font-bold text-white transition hover:bg-white/25 sm:px-6 sm:py-1.5'>
|
||||||
|
{tHome('viewSubscriptionPlans')}
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
ref={dialogRef}
|
ref={dialogRef}
|
||||||
className='rounded-0 h-full gap-0 px-4 py-8 sm:max-h-[95%] sm:!rounded-[32px] sm:px-8 sm:py-12 md:max-w-[1280px]'
|
className='rounded-0 h-full gap-0 px-4 py-8 sm:max-h-[95%] sm:!rounded-[32px] sm:px-8 sm:py-12 md:max-w-[1280px]'
|
||||||
>
|
>
|
||||||
<DialogTitle className={'sr-only'}></DialogTitle>
|
<DialogTitle className={'sr-only'}></DialogTitle>
|
||||||
<div className={'ml-6 sm:ml-0'}>
|
<div className={'ml-6 sm:ml-0'}>
|
||||||
<div className={'text-4xl font-bold text-[#0F2C53] md:mb-4 md:text-center md:text-5xl'}>
|
<div className={'text-4xl font-bold text-[#0F2C53] md:mb-1 md:text-center'}>
|
||||||
{t('selectPlan')}
|
{t('selectPlan')}
|
||||||
</div>
|
</div>
|
||||||
<div className={'text-lg font-medium text-[#666666] md:text-center'}>
|
<div className={'text-base font-medium text-[#666666] md:text-center'}>
|
||||||
{t('selectYourPlan')}
|
{t('selectYourPlan')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -80,6 +81,6 @@ const OfferDialog = forwardRef<OfferDialogRef>((props, ref) => {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
export default OfferDialog;
|
export default OfferDialog;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import PlanTabs, { TabValueType } from '@/components/SubscribePlan/PlanTabs/Plan
|
|||||||
import useGlobalStore from '@/config/use-global';
|
import useGlobalStore from '@/config/use-global';
|
||||||
import { preCreateOrder, purchase } from '@/services/user/order';
|
import { preCreateOrder, purchase } from '@/services/user/order';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -164,14 +164,10 @@ const Purchase = forwardRef<PurchaseDialogRef, PurchaseProps>((props, ref) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='mt-8 flex items-center justify-center'>
|
<div className='mt-8 flex items-center justify-center'>
|
||||||
<Button
|
<AiroButton variant={'primary'} disabled={loading} onClick={handleSubmit}>
|
||||||
className='w-[150px] rounded-full border-[#A8D4ED] bg-[#A8D4ED] text-xl hover:bg-[#225BA9] hover:text-white'
|
|
||||||
disabled={loading}
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>
|
|
||||||
{loading && <LoaderCircle className='mr-2 animate-spin' />}
|
{loading && <LoaderCircle className='mr-2 animate-spin' />}
|
||||||
{t('buyNow')}
|
{t('buyNow')}
|
||||||
</Button>
|
</AiroButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import useGlobalStore from '@/config/use-global';
|
|||||||
import { preCreateOrder, renewal } from '@/services/user/order';
|
import { preCreateOrder, renewal } from '@/services/user/order';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
|
||||||
import { Button } from '@workspace/airo-ui/components/button';
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@ -103,9 +102,9 @@ export default function Renewal({ id, subscribe, className }: Readonly<RenewalPr
|
|||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button size='sm' className={className}>
|
<AiroButton variant={'primaryBlue'} className={'px-2 text-xs'}>
|
||||||
{t('renewPlan')}
|
{t('renewPlan')}
|
||||||
</Button>
|
</AiroButton>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className='flex h-full flex-col md:h-auto'>
|
<DialogContent className='flex h-full flex-col md:h-auto'>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"annualPackage": "Annual Package",
|
"annualPackage": "Annual Package",
|
||||||
"commissionCalculation": "Commission Calculation",
|
"commissionCalculation": "Commission Calculation",
|
||||||
"commissionCalculationInfo": "Fill in the corresponding number of invited users below to calculate the commission amount at different ratios. *This table is calculated based on the Pro Plan. The ratios for other plans remain unchanged, and the calculation is based on the actual amount.",
|
"commissionCalculationInfo": "Fill in the corresponding number of invited users below to calculate the commission amount at different ratios. \n *This table is calculated based on the Pro Plan. The ratios for other plans remain unchanged, and the calculation is based on the actual amount.",
|
||||||
"commissionInfo": "Commission amount, which is automatically transferred to the wallet balance after a successful invitation.",
|
"commissionInfo": "Commission amount, which is automatically transferred to the wallet balance after a successful invitation.",
|
||||||
"commissionInviteCode": "Commission Invite Code",
|
"commissionInviteCode": "Commission Invite Code",
|
||||||
"commissionRate": "Commission Rate",
|
"commissionRate": "Commission Rate",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"annualPackage": "年付套餐",
|
"annualPackage": "年付套餐",
|
||||||
"commissionCalculation": "佣金计算",
|
"commissionCalculation": "佣金计算",
|
||||||
"commissionCalculationInfo": "在下方填入对应邀请用户数量,即可计算不同比例返佣金额 *该表以Pro Plan计算,其它套餐比例不变,以实际金额计算为准",
|
"commissionCalculationInfo": "在下方填入对应邀请用户数量,即可计算不同比例返佣金额 \n *该表以Pro Plan计算,其它套餐比例不变,以实际金额计算为准",
|
||||||
"commissionInfo": "佣金金额,邀请成功后自动转入钱包余额",
|
"commissionInfo": "佣金金额,邀请成功后自动转入钱包余额",
|
||||||
"commissionInviteCode": "返佣邀请码",
|
"commissionInviteCode": "返佣邀请码",
|
||||||
"commissionRate": "佣金比例",
|
"commissionRate": "佣金比例",
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
import baseConfig from '@workspace/airo-ui/tailwind.config';
|
import baseConfig from '@workspace/airo-ui/tailwind.config';
|
||||||
|
|
||||||
|
baseConfig.theme.extend.boxShadow = {
|
||||||
|
...baseConfig.theme.extend.boxShadow,
|
||||||
|
...{
|
||||||
|
input: 'inset 0 0 7.6px 0 rgba(0, 0, 0, 0.25) ',
|
||||||
|
},
|
||||||
|
};
|
||||||
const config = {
|
const config = {
|
||||||
...baseConfig,
|
...baseConfig,
|
||||||
darkMode: false, // 或 'media' 或 'class',根据你的需求覆盖
|
darkMode: false, // 或 'media' 或 'class',根据你的需求覆盖
|
||||||
|
|||||||
@ -13,6 +13,7 @@ const buttonVariants = cva(
|
|||||||
primary: 'bg-[#225BA9] text-primary-foreground shadow hover:bg-[#0F2C53] ',
|
primary: 'bg-[#225BA9] text-primary-foreground shadow hover:bg-[#0F2C53] ',
|
||||||
danger: 'bg-[#FF4248] text-primary-foreground shadow hover:bg-[#E22C2E]',
|
danger: 'bg-[#FF4248] text-primary-foreground shadow hover:bg-[#E22C2E]',
|
||||||
dangerLink: 'text-[#E22C2E] ',
|
dangerLink: 'text-[#E22C2E] ',
|
||||||
|
primaryBlue: 'bg-[#A8D4ED] text-primary-foreground hover:bg-[#225BA9]',
|
||||||
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
||||||
outline:
|
outline:
|
||||||
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import * as React from 'react';
|
|||||||
import { cn } from '@workspace/airo-ui/lib/utils';
|
import { cn } from '@workspace/airo-ui/lib/utils';
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
|
|||||||
@ -133,42 +133,44 @@ export function ProList<TData, TValue extends Record<string, unknown>>({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex max-w-full flex-col gap-2 sm:gap-4'>
|
<div className='flex max-w-full flex-col gap-2 sm:gap-4'>
|
||||||
<div className='flex flex-wrap-reverse items-center justify-between gap-4'>
|
{params || header ? (
|
||||||
<div className={'w-full'}>
|
<div className='flex flex-wrap-reverse items-center justify-between gap-4'>
|
||||||
{params ? (
|
<div className={'w-full'}>
|
||||||
<div className='flex w-full justify-between'>
|
{params ? (
|
||||||
<ColumnFilter
|
<div className='flex w-full justify-between'>
|
||||||
table={table}
|
<ColumnFilter
|
||||||
params={params}
|
table={table}
|
||||||
filters={Object.fromEntries(columnFilters.map((item) => [item.id, item.value]))}
|
params={params}
|
||||||
/>
|
filters={Object.fromEntries(columnFilters.map((item) => [item.id, item.value]))}
|
||||||
<Button
|
/>
|
||||||
variant='outline'
|
<Button
|
||||||
className='h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:hidden'
|
variant='outline'
|
||||||
onClick={fetchData}
|
className='h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:hidden'
|
||||||
>
|
onClick={fetchData}
|
||||||
<RefreshCcw className='h-4 w-4 text-[#848484]' />
|
>
|
||||||
</Button>
|
<RefreshCcw className='h-4 w-4 text-[#848484]' />
|
||||||
</div>
|
</Button>
|
||||||
) : (
|
</div>
|
||||||
header?.title
|
) : (
|
||||||
)}
|
header?.title
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-1 items-center justify-end gap-2'>
|
||||||
|
{params && params?.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant='outline'
|
||||||
|
className='hidden h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:block'
|
||||||
|
onClick={fetchData}
|
||||||
|
>
|
||||||
|
<RefreshCcw className='h-4 w-4 text-[#848484]' />
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{header?.toolbar}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-1 items-center justify-end gap-2'>
|
) : null}
|
||||||
{params && params?.length > 0 && (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
variant='outline'
|
|
||||||
className='hidden h-8 w-8 rounded-full bg-[#D9D9D9] p-2 sm:block'
|
|
||||||
onClick={fetchData}
|
|
||||||
>
|
|
||||||
<RefreshCcw className='h-4 w-4 text-[#848484]' />
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{header?.toolbar}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{selectedCount > 0 && batchRender && (
|
{selectedCount > 0 && batchRender && (
|
||||||
<Alert className='flex items-center justify-between'>
|
<Alert className='flex items-center justify-between'>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user