Skip to content

Commit

Permalink
✨ feat(affiliate): Update affiliate component to display total commis…
Browse files Browse the repository at this point in the history
…sion and improve data fetching
  • Loading branch information
web-ppanel committed Jan 4, 2025
1 parent 4aea4e8 commit cc834ca
Show file tree
Hide file tree
Showing 56 changed files with 335 additions and 114 deletions.
9 changes: 6 additions & 3 deletions apps/admin/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import packageJSON from '../package.json';
export const locales = packageJSON.i18n.outputLocales;
export const defaultLocale = packageJSON.i18n.entry;

export const NEXT_PUBLIC_DEFAULT_LANGUAGE = env('NEXT_PUBLIC_DEFAULT_LANGUAGE') ?? defaultLocale;
export const NEXT_PUBLIC_DEFAULT_LANGUAGE =
env('NEXT_PUBLIC_DEFAULT_LANGUAGE') ?? process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE ?? defaultLocale;

export const NEXT_PUBLIC_SITE_URL = env('NEXT_PUBLIC_SITE_URL') ?? process.env.NEXT_PUBLIC_SITE_URL;
export const NEXT_PUBLIC_API_URL = env('NEXT_PUBLIC_API_URL') ?? process.env.NEXT_PUBLIC_API_URL;

export const NEXT_PUBLIC_DEFAULT_USER_EMAIL = env('NEXT_PUBLIC_DEFAULT_USER_EMAIL');
export const NEXT_PUBLIC_DEFAULT_USER_PASSWORD = env('NEXT_PUBLIC_DEFAULT_USER_PASSWORD');
export const NEXT_PUBLIC_DEFAULT_USER_EMAIL =
env('NEXT_PUBLIC_DEFAULT_USER_EMAIL') ?? process.env.NEXT_PUBLIC_DEFAULT_USER_EMAIL;
export const NEXT_PUBLIC_DEFAULT_USER_PASSWORD =
env('NEXT_PUBLIC_DEFAULT_USER_PASSWORD') ?? process.env.NEXT_PUBLIC_DEFAULT_USER_PASSWORD;
14 changes: 7 additions & 7 deletions apps/admin/services/admin/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ declare namespace API {
show: boolean;
sell: boolean;
deduction_ratio: number;
purchase_with_discount: boolean;
allow_deduction: boolean;
reset_cycle: number;
renewal_reset: boolean;
};
Expand Down Expand Up @@ -548,6 +548,7 @@ declare namespace API {
quantity: number;
price: number;
amount: number;
deduction: number;
discount: number;
coupon: string;
coupon_discount: number;
Expand All @@ -556,8 +557,6 @@ declare namespace API {
trade_no: string;
status: number;
subscribe_id: number;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
Expand All @@ -570,6 +569,7 @@ declare namespace API {
quantity: number;
price: number;
amount: number;
deduction: number;
discount: number;
coupon: string;
coupon_discount: number;
Expand All @@ -579,8 +579,6 @@ declare namespace API {
status: number;
subscribe_id: number;
subscribe: Subscribe;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
Expand Down Expand Up @@ -747,7 +745,7 @@ declare namespace API {
sell: boolean;
sort: number;
deduction_ratio: number;
purchase_with_discount: boolean;
allow_deduction: boolean;
reset_cycle: number;
renewal_reset: boolean;
created_at: number;
Expand Down Expand Up @@ -975,7 +973,7 @@ declare namespace API {
sell: boolean;
sort: number;
deduction_ratio: number;
purchase_with_discount: boolean;
allow_deduction: boolean;
reset_cycle: number;
renewal_reset: boolean;
};
Expand Down Expand Up @@ -1010,6 +1008,8 @@ declare namespace API {
email: string;
avatar: string;
balance: number;
commission: number;
deduction: number;
telegram: number;
refer_code: string;
referer_id: number;
Expand Down
10 changes: 5 additions & 5 deletions apps/admin/services/common/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ declare namespace API {
quantity: number;
price: number;
amount: number;
deduction: number;
discount: number;
coupon: string;
coupon_discount: number;
Expand All @@ -173,8 +174,6 @@ declare namespace API {
trade_no: string;
status: number;
subscribe_id: number;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
Expand All @@ -187,6 +186,7 @@ declare namespace API {
quantity: number;
price: number;
amount: number;
deduction: number;
discount: number;
coupon: string;
coupon_discount: number;
Expand All @@ -196,8 +196,6 @@ declare namespace API {
status: number;
subscribe_id: number;
subscribe: Subscribe;
subscription_discount_id: number;
subscription_discount_price: number;
created_at: number;
updated_at: number;
};
Expand Down Expand Up @@ -333,7 +331,7 @@ declare namespace API {
sell: boolean;
sort: number;
deduction_ratio: number;
purchase_with_discount: boolean;
allow_deduction: boolean;
reset_cycle: number;
renewal_reset: boolean;
created_at: number;
Expand Down Expand Up @@ -416,6 +414,8 @@ declare namespace API {
email: string;
avatar: string;
balance: number;
commission: number;
deduction: number;
telegram: number;
refer_code: string;
referer_id: number;
Expand Down
62 changes: 40 additions & 22 deletions apps/user/app/(main)/(user)/sidebar-right.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,48 @@ export function SidebarRight({ ...props }: React.ComponentProps<typeof Sidebar>)
</CardContent>
</Card>
<Card>
<CardHeader className='flex flex-row items-center justify-between space-y-0 p-3 pb-2'>
<CardTitle className='text-sm font-medium'>{t('inviteCode')}</CardTitle>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<CopyToClipboard
text={`${isBrowser() && location?.origin}/auth?invite=${user?.refer_code}`}
onCopy={(text, result) => {
if (result) {
toast.success(t('copySuccess'));
}
}}
>
<Button variant='ghost' className='size-5 p-0'>
<Icon icon='mdi:content-copy' className='text-primary text-2xl' />
</Button>
</CopyToClipboard>
</TooltipTrigger>
<TooltipContent>{t('copyInviteLink')}</TooltipContent>
</Tooltip>
</TooltipProvider>
<CardHeader className='space-y-0 p-3 pb-2'>
<CardTitle className='text-sm font-medium'>{t('deductBalance')}</CardTitle>
</CardHeader>
<CardContent className='p-3 text-2xl font-bold'>
<Display type='currency' value={user?.deduction} />
</CardContent>
</Card>
<Card>
<CardHeader className='space-y-0 p-3 pb-2'>
<CardTitle className='text-sm font-medium'>{t('commission')}</CardTitle>
</CardHeader>
<CardContent className='truncate p-3 font-bold'>{user?.refer_code}</CardContent>
<CardContent className='p-3 text-2xl font-bold'>
<Display type='currency' value={user?.commission} />
</CardContent>
</Card>
{user?.refer_code && (
<Card>
<CardHeader className='flex flex-row items-center justify-between space-y-0 p-3 pb-2'>
<CardTitle className='text-sm font-medium'>{t('inviteCode')}</CardTitle>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<CopyToClipboard
text={`${isBrowser() && location?.origin}/auth?invite=${user?.refer_code}`}
onCopy={(text, result) => {
if (result) {
toast.success(t('copySuccess'));
}
}}
>
<Button variant='ghost' className='size-5 p-0'>
<Icon icon='mdi:content-copy' className='text-primary text-2xl' />
</Button>
</CopyToClipboard>
</TooltipTrigger>
<TooltipContent>{t('copyInviteLink')}</TooltipContent>
</Tooltip>
</TooltipProvider>
</CardHeader>
<CardContent className='truncate p-3 font-bold'>{user?.refer_code}</CardContent>
</Card>
)}
</SidebarContent>
</Sidebar>
);
Expand Down
49 changes: 39 additions & 10 deletions apps/user/app/(main)/(user)/wallet/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Display } from '@/components/display';
import { ProList, ProListActions } from '@/components/pro-list';
import useGlobalStore from '@/config/use-global';
import { queryUserBalanceLog } from '@/services/user/user';
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card';
import { Card, CardContent } from '@workspace/ui/components/card';
import { useTranslations } from 'next-intl';
import { useRef } from 'react';

Expand All @@ -16,19 +16,48 @@ export default function Page() {
const t = useTranslations('wallet');
const { user } = useGlobalStore();
const ref = useRef<ProListActions>(null);

const totalAssets = (user?.balance || 0) + (user?.commission || 0) + (user?.deduction || 0);
return (
<>
<Card className='mb-4'>
<CardHeader>
<CardTitle className='font-medium'>{t('title')}</CardTitle>
</CardHeader>
<CardContent className='flex items-center justify-between'>
<div className='text-2xl font-bold'>
<Display type='currency' value={user?.balance} />
<CardContent className='p-6'>
<h2 className='text-foreground mb-4 text-2xl font-bold'>{t('totalAssets')}</h2>
<div className='mb-4'>
<div className='flex items-center justify-between'>
<div>
<p className='text-sm font-medium'>总资产</p>
<p className='text-3xl font-bold'>
<Display type='currency' value={totalAssets} />
</p>
</div>
<Recharge />
</div>
</div>
<div className='flex gap-2'>
<Recharge />
<div className='grid grid-cols-1 gap-6 md:grid-cols-3'>
<div className='bg-secondary rounded-lg p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
<p className='text-secondary-foreground text-sm font-medium opacity-80'>
{t('balance')}
</p>
<p className='text-secondary-foreground text-2xl font-bold'>
<Display type='currency' value={user?.balance} />
</p>
</div>
<div className='bg-secondary rounded-lg p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
<p className='text-secondary-foreground text-sm font-medium opacity-80'>
{t('deductBalance')}
</p>
<p className='text-secondary-foreground text-2xl font-bold'>
<Display type='currency' value={user?.deduction} />
</p>
</div>
<div className='bg-secondary rounded-lg p-4 shadow-sm transition-all duration-300 hover:shadow-md'>
<p className='text-secondary-foreground text-sm font-medium opacity-80'>
{t('commission')}
</p>
<p className='text-secondary-foreground text-2xl font-bold'>
<Display type='currency' value={user?.commission} />
</p>
</div>
</div>
</CardContent>
</Card>
Expand Down
16 changes: 12 additions & 4 deletions apps/user/components/affiliate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Display } from '@/components/display';
import { Empty } from '@/components/empty';
import { ProList } from '@/components/pro-list';
import useGlobalStore from '@/config/use-global';
import { queryUserAffiliate } from '@/services/user/user';
import { queryUserAffiliate, queryUserAffiliateList } from '@/services/user/user';
import { useQuery } from '@tanstack/react-query';
import { Button } from '@workspace/ui/components/button';
import {
Card,
Expand All @@ -24,6 +25,13 @@ export default function Affiliate() {
const t = useTranslations('affiliate');
const { user, common } = useGlobalStore();
const [sum, setSum] = useState<number>();
const { data } = useQuery({
queryKey: ['queryUserAffiliate'],
queryFn: async () => {
const response = await queryUserAffiliate();
return response.data.data;
},
});

return (
<div className='flex flex-col gap-4'>
Expand All @@ -35,7 +43,7 @@ export default function Affiliate() {
<CardContent>
<div className='flex items-baseline gap-2'>
<span className='text-3xl font-bold'>
<Display type='currency' value={sum} />
<Display type='currency' value={data?.total_commission} />
</span>
<span className='text-muted-foreground text-sm'>
({t('commissionRate')}: {common?.invite?.referral_percentage}%)
Expand All @@ -53,7 +61,7 @@ export default function Affiliate() {
{user?.refer_code}
</code>
<CopyToClipboard
text={`${location.origin}/auth?invite=${user?.refer_code}`}
text={`${location?.origin}/auth?invite=${user?.refer_code}`}
onCopy={(text, result) => {
if (result) {
toast.success(t('copySuccess'));
Expand All @@ -70,7 +78,7 @@ export default function Affiliate() {
</Card>
<ProList<API.UserAffiliate, Record<string, unknown>>
request={async (pagination, filter) => {
const response = await queryUserAffiliate({ ...pagination, ...filter });
const response = await queryUserAffiliateList({ ...pagination, ...filter });
setSum(response.data.data?.sum);
return {
list: response.data.data?.list || [],
Expand Down
29 changes: 19 additions & 10 deletions apps/user/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@ import packageJSON from '../package.json';
export const locales = packageJSON.i18n.outputLocales;
export const defaultLocale = packageJSON.i18n.entry;

export const NEXT_PUBLIC_DEFAULT_LANGUAGE = env('NEXT_PUBLIC_DEFAULT_LANGUAGE') ?? defaultLocale;
export const NEXT_PUBLIC_DEFAULT_LANGUAGE =
env('NEXT_PUBLIC_DEFAULT_LANGUAGE') ?? process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE ?? defaultLocale;

export const NEXT_PUBLIC_SITE_URL = env('NEXT_PUBLIC_SITE_URL') ?? process.env.NEXT_PUBLIC_SITE_URL;
export const NEXT_PUBLIC_API_URL = env('NEXT_PUBLIC_API_URL') ?? process.env.NEXT_PUBLIC_API_URL;

export const NEXT_PUBLIC_DEFAULT_USER_EMAIL = env('NEXT_PUBLIC_DEFAULT_USER_EMAIL');
export const NEXT_PUBLIC_DEFAULT_USER_PASSWORD = env('NEXT_PUBLIC_DEFAULT_USER_PASSWORD');
export const NEXT_PUBLIC_DEFAULT_USER_EMAIL =
env('NEXT_PUBLIC_DEFAULT_USER_EMAIL') ?? process.env.NEXT_PUBLIC_DEFAULT_USER_EMAIL;
export const NEXT_PUBLIC_DEFAULT_USER_PASSWORD =
env('NEXT_PUBLIC_DEFAULT_USER_PASSWORD') ?? process.env.NEXT_PUBLIC_DEFAULT_USER_PASSWORD;

export const NEXT_PUBLIC_EMAIL = env('NEXT_PUBLIC_EMAIL');
export const NEXT_PUBLIC_EMAIL = env('NEXT_PUBLIC_EMAIL') ?? process.env.NEXT_PUBLIC_EMAIL;

export const NEXT_PUBLIC_TELEGRAM_LINK = env('NEXT_PUBLIC_TELEGRAM_LINK');
export const NEXT_PUBLIC_DISCORD_LINK = env('NEXT_PUBLIC_DISCORD_LINK');
export const NEXT_PUBLIC_GITHUB_LINK = env('NEXT_PUBLIC_GITHUB_LINK');
export const NEXT_PUBLIC_LINKEDIN_LINK = env('NEXT_PUBLIC_LINKEDIN_LINK');
export const NEXT_PUBLIC_TWITTER_LINK = env('NEXT_PUBLIC_TWITTER_LINK');
export const NEXT_PUBLIC_INSTAGRAM_LINK = env('NEXT_PUBLIC_INSTAGRAM_LINK');
export const NEXT_PUBLIC_TELEGRAM_LINK =
env('NEXT_PUBLIC_TELEGRAM_LINK') ?? process.env.NEXT_PUBLIC_TELEGRAM_LINK;
export const NEXT_PUBLIC_DISCORD_LINK =
env('NEXT_PUBLIC_DISCORD_LINK') ?? process.env.NEXT_PUBLIC_DISCORD_LINK;
export const NEXT_PUBLIC_GITHUB_LINK =
env('NEXT_PUBLIC_GITHUB_LINK') ?? process.env.NEXT_PUBLIC_GITHUB_LINK;
export const NEXT_PUBLIC_LINKEDIN_LINK =
env('NEXT_PUBLIC_LINKEDIN_LINK') ?? process.env.NEXT_PUBLIC_LINKEDIN_LINK;
export const NEXT_PUBLIC_TWITTER_LINK =
env('NEXT_PUBLIC_TWITTER_LINK') ?? process.env.NEXT_PUBLIC_TWITTER_LINK;
export const NEXT_PUBLIC_INSTAGRAM_LINK =
env('NEXT_PUBLIC_INSTAGRAM_LINK') ?? process.env.NEXT_PUBLIC_INSTAGRAM_LINK;
2 changes: 2 additions & 0 deletions apps/user/locales/cs-CZ/layout.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"accountBalance": "Zůstatek na účtu",
"commission": "Provize",
"copyInviteLink": "Zkopírovat odkaz na pozvánku",
"copySuccess": "Odkaz na pozvánku byl úspěšně zkopírován",
"deductBalance": "Odečíst zůstatek",
"inviteCode": "pozvánkový kód",
"recharge": "Dobít"
}
4 changes: 3 additions & 1 deletion apps/user/locales/cs-CZ/wallet.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
{
"amount": "Částka",
"balance": "zůstatek",
"commission": "Provize",
"createdAt": "čas",
"title": "Zůstatek na účtu",
"deductBalance": "Odečíst zůstatek",
"totalAssets": "Přehled aktiv",
"type": {
"0": "Typ",
"1": "Dobití",
Expand Down
2 changes: 2 additions & 0 deletions apps/user/locales/de-DE/layout.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"accountBalance": "Kontostand",
"commission": "Provision",
"copyInviteLink": "Einladungslink kopieren",
"copySuccess": "Einladungslink erfolgreich kopiert",
"deductBalance": "Guthaben abziehen",
"inviteCode": "Einladungscode",
"recharge": "Aufladen"
}
Loading

0 comments on commit cc834ca

Please sign in to comment.