feat: add subscription renewal and lifetime monthly messages in English and Chinese
This commit is contained in:
parent
0500617803
commit
2aeb027e2f
@ -633,7 +633,9 @@
|
|||||||
"REGISTER_GIFT": "Register Gift",
|
"REGISTER_GIFT": "Register Gift",
|
||||||
"PURCHASE": "Purchase",
|
"PURCHASE": "Purchase",
|
||||||
"USAGE": "Usage",
|
"USAGE": "Usage",
|
||||||
"EXPIRE": "Expire"
|
"EXPIRE": "Expire",
|
||||||
|
"SUBSCRIPTION_RENEWAL": "Subscription Renewal",
|
||||||
|
"LIFETIME_MONTHLY": "Lifetime Monthly"
|
||||||
},
|
},
|
||||||
"expired": "Expired",
|
"expired": "Expired",
|
||||||
"never": "Never"
|
"never": "Never"
|
||||||
|
@ -634,7 +634,9 @@
|
|||||||
"REGISTER_GIFT": "注册礼品",
|
"REGISTER_GIFT": "注册礼品",
|
||||||
"PURCHASE": "购买",
|
"PURCHASE": "购买",
|
||||||
"USAGE": "使用",
|
"USAGE": "使用",
|
||||||
"EXPIRE": "过期"
|
"EXPIRE": "过期",
|
||||||
|
"SUBSCRIPTION_RENEWAL": "订阅续费",
|
||||||
|
"LIFETIME_MONTHLY": "终身月度"
|
||||||
},
|
},
|
||||||
"expired": "已过期",
|
"expired": "已过期",
|
||||||
"never": "永不"
|
"never": "永不"
|
||||||
|
@ -23,6 +23,13 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from '@/components/ui/table';
|
} from '@/components/ui/table';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
|
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
|
||||||
import { formatDate } from '@/lib/formatter';
|
import { formatDate } from '@/lib/formatter';
|
||||||
import {
|
import {
|
||||||
type ColumnDef,
|
type ColumnDef,
|
||||||
@ -43,18 +50,17 @@ import {
|
|||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
ChevronsLeftIcon,
|
ChevronsLeftIcon,
|
||||||
ChevronsRightIcon,
|
ChevronsRightIcon,
|
||||||
RefreshCwIcon,
|
|
||||||
GiftIcon,
|
|
||||||
ShoppingCartIcon,
|
|
||||||
MinusCircleIcon,
|
|
||||||
ClockIcon,
|
ClockIcon,
|
||||||
|
GiftIcon,
|
||||||
|
MinusCircleIcon,
|
||||||
|
RefreshCwIcon,
|
||||||
|
ShoppingCartIcon,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Badge } from '../../ui/badge';
|
import { Badge } from '../../ui/badge';
|
||||||
import { Label } from '../../ui/label';
|
import { Label } from '../../ui/label';
|
||||||
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
|
|
||||||
|
|
||||||
// Define the credit transaction interface
|
// Define the credit transaction interface
|
||||||
interface CreditTransaction {
|
interface CreditTransaction {
|
||||||
@ -109,8 +115,6 @@ interface CreditTransactionsTableProps {
|
|||||||
onSortingChange?: (sorting: SortingState) => void;
|
onSortingChange?: (sorting: SortingState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { type CreditTransaction };
|
|
||||||
|
|
||||||
export function CreditTransactionsTable({
|
export function CreditTransactionsTable({
|
||||||
data,
|
data,
|
||||||
total,
|
total,
|
||||||
@ -126,7 +130,7 @@ export function CreditTransactionsTable({
|
|||||||
const t = useTranslations('Dashboard.settings.credits.transactions');
|
const t = useTranslations('Dashboard.settings.credits.transactions');
|
||||||
const tTable = useTranslations('Common.table');
|
const tTable = useTranslations('Common.table');
|
||||||
const [sorting, setSorting] = useState<SortingState>([
|
const [sorting, setSorting] = useState<SortingState>([
|
||||||
{ id: 'createdAt', desc: true }
|
{ id: 'createdAt', desc: true },
|
||||||
]);
|
]);
|
||||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
@ -147,39 +151,42 @@ export function CreditTransactionsTable({
|
|||||||
updatedAt: 'columns.updatedAt' as const,
|
updatedAt: 'columns.updatedAt' as const,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Get transaction type icon and color
|
// Get transaction type icon
|
||||||
const getTransactionTypeIcon = (type: string) => {
|
const getTransactionTypeIcon = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CREDIT_TRANSACTION_TYPE.MONTHLY_REFRESH:
|
case CREDIT_TRANSACTION_TYPE.MONTHLY_REFRESH:
|
||||||
return <RefreshCwIcon className="h-4 w-4 text-blue-500" />;
|
return <RefreshCwIcon className="h-4 w-4" />;
|
||||||
case CREDIT_TRANSACTION_TYPE.REGISTER_GIFT:
|
case CREDIT_TRANSACTION_TYPE.REGISTER_GIFT:
|
||||||
return <GiftIcon className="h-4 w-4 text-green-500" />;
|
return <GiftIcon className="h-4 w-4" />;
|
||||||
case CREDIT_TRANSACTION_TYPE.PURCHASE:
|
case CREDIT_TRANSACTION_TYPE.PURCHASE:
|
||||||
return <ShoppingCartIcon className="h-4 w-4 text-purple-500" />;
|
return <ShoppingCartIcon className="h-4 w-4" />;
|
||||||
case CREDIT_TRANSACTION_TYPE.USAGE:
|
case CREDIT_TRANSACTION_TYPE.USAGE:
|
||||||
return <MinusCircleIcon className="h-4 w-4 text-red-500" />;
|
return <MinusCircleIcon className="h-4 w-4" />;
|
||||||
case CREDIT_TRANSACTION_TYPE.EXPIRE:
|
case CREDIT_TRANSACTION_TYPE.EXPIRE:
|
||||||
return <ClockIcon className="h-4 w-4 text-gray-500" />;
|
return <ClockIcon className="h-4 w-4" />;
|
||||||
|
case CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL:
|
||||||
|
return <RefreshCwIcon className="h-4 w-4" />;
|
||||||
|
case CREDIT_TRANSACTION_TYPE.LIFETIME_MONTHLY:
|
||||||
|
return <GiftIcon className="h-4 w-4" />;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get transaction type color
|
// Get transaction type badge variant
|
||||||
const getTransactionTypeColor = (type: string) => {
|
const getTransactionTypeBadgeVariant = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CREDIT_TRANSACTION_TYPE.MONTHLY_REFRESH:
|
|
||||||
return 'bg-blue-100 text-blue-800 border-blue-200';
|
|
||||||
case CREDIT_TRANSACTION_TYPE.REGISTER_GIFT:
|
case CREDIT_TRANSACTION_TYPE.REGISTER_GIFT:
|
||||||
return 'bg-green-100 text-green-800 border-green-200';
|
|
||||||
case CREDIT_TRANSACTION_TYPE.PURCHASE:
|
case CREDIT_TRANSACTION_TYPE.PURCHASE:
|
||||||
return 'bg-purple-100 text-purple-800 border-purple-200';
|
case CREDIT_TRANSACTION_TYPE.MONTHLY_REFRESH:
|
||||||
|
case CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL:
|
||||||
|
case CREDIT_TRANSACTION_TYPE.LIFETIME_MONTHLY:
|
||||||
|
return 'outline' as const;
|
||||||
case CREDIT_TRANSACTION_TYPE.USAGE:
|
case CREDIT_TRANSACTION_TYPE.USAGE:
|
||||||
return 'bg-red-100 text-red-800 border-red-200';
|
|
||||||
case CREDIT_TRANSACTION_TYPE.EXPIRE:
|
case CREDIT_TRANSACTION_TYPE.EXPIRE:
|
||||||
return 'bg-gray-100 text-gray-800 border-gray-200';
|
return 'destructive' as const;
|
||||||
default:
|
default:
|
||||||
return 'bg-gray-100 text-gray-800 border-gray-200';
|
return 'outline' as const;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -196,6 +203,10 @@ export function CreditTransactionsTable({
|
|||||||
return t('types.USAGE');
|
return t('types.USAGE');
|
||||||
case CREDIT_TRANSACTION_TYPE.EXPIRE:
|
case CREDIT_TRANSACTION_TYPE.EXPIRE:
|
||||||
return t('types.EXPIRE');
|
return t('types.EXPIRE');
|
||||||
|
case CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL:
|
||||||
|
return t('types.SUBSCRIPTION_RENEWAL');
|
||||||
|
case CREDIT_TRANSACTION_TYPE.LIFETIME_MONTHLY:
|
||||||
|
return t('types.LIFETIME_MONTHLY');
|
||||||
default:
|
default:
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@ -212,10 +223,7 @@ export function CreditTransactionsTable({
|
|||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2 pl-3">
|
<div className="flex items-center gap-2 pl-3">
|
||||||
<Badge
|
<Badge variant={getTransactionTypeBadgeVariant(transaction.type)}>
|
||||||
variant="outline"
|
|
||||||
className={`px-2 py-1 flex items-center gap-1 ${getTransactionTypeColor(transaction.type)}`}
|
|
||||||
>
|
|
||||||
{getTransactionTypeIcon(transaction.type)}
|
{getTransactionTypeIcon(transaction.type)}
|
||||||
{getTransactionTypeDisplayName(transaction.type)}
|
{getTransactionTypeDisplayName(transaction.type)}
|
||||||
</Badge>
|
</Badge>
|
||||||
@ -247,7 +255,10 @@ export function CreditTransactionsTable({
|
|||||||
{
|
{
|
||||||
accessorKey: 'remainingAmount',
|
accessorKey: 'remainingAmount',
|
||||||
header: ({ column }) => (
|
header: ({ column }) => (
|
||||||
<DataTableColumnHeader column={column} title={t('columns.remainingAmount')} />
|
<DataTableColumnHeader
|
||||||
|
column={column}
|
||||||
|
title={t('columns.remainingAmount')}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
@ -267,15 +278,33 @@ export function CreditTransactionsTable({
|
|||||||
{
|
{
|
||||||
accessorKey: 'description',
|
accessorKey: 'description',
|
||||||
header: ({ column }) => (
|
header: ({ column }) => (
|
||||||
<DataTableColumnHeader column={column} title={t('columns.description')} />
|
<DataTableColumnHeader
|
||||||
|
column={column}
|
||||||
|
title={t('columns.description')}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2 pl-3">
|
<div className="flex items-center gap-2 pl-3">
|
||||||
<span className="max-w-[200px] truncate" title={transaction.description || undefined}>
|
{transaction.description ? (
|
||||||
{transaction.description || '-'}
|
<TooltipProvider>
|
||||||
</span>
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<span className="max-w-[200px] truncate cursor-help">
|
||||||
|
{transaction.description}
|
||||||
|
</span>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p className="max-w-xs whitespace-pre-wrap">
|
||||||
|
{transaction.description}
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
) : (
|
||||||
|
<span className="text-gray-400">-</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -310,7 +339,10 @@ export function CreditTransactionsTable({
|
|||||||
{
|
{
|
||||||
accessorKey: 'expirationDate',
|
accessorKey: 'expirationDate',
|
||||||
header: ({ column }) => (
|
header: ({ column }) => (
|
||||||
<DataTableColumnHeader column={column} title={t('columns.expirationDate')} />
|
<DataTableColumnHeader
|
||||||
|
column={column}
|
||||||
|
title={t('columns.expirationDate')}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
@ -330,7 +362,10 @@ export function CreditTransactionsTable({
|
|||||||
{
|
{
|
||||||
accessorKey: 'expirationDateProcessedAt',
|
accessorKey: 'expirationDateProcessedAt',
|
||||||
header: ({ column }) => (
|
header: ({ column }) => (
|
||||||
<DataTableColumnHeader column={column} title={t('columns.expirationDateProcessedAt')} />
|
<DataTableColumnHeader
|
||||||
|
column={column}
|
||||||
|
title={t('columns.expirationDateProcessedAt')}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
@ -356,9 +391,7 @@ export function CreditTransactionsTable({
|
|||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2 pl-3">
|
<div className="flex items-center gap-2 pl-3">
|
||||||
<span className="text-sm">
|
<span className="text-sm">{formatDate(transaction.createdAt)}</span>
|
||||||
{formatDate(transaction.createdAt)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -372,9 +405,7 @@ export function CreditTransactionsTable({
|
|||||||
const transaction = row.original;
|
const transaction = row.original;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2 pl-3">
|
<div className="flex items-center gap-2 pl-3">
|
||||||
<span className="text-sm">
|
<span className="text-sm">{formatDate(transaction.updatedAt)}</span>
|
||||||
{formatDate(transaction.updatedAt)}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -514,11 +545,7 @@ export function CreditTransactionsTable({
|
|||||||
|
|
||||||
<div className="flex items-center justify-between px-4">
|
<div className="flex items-center justify-between px-4">
|
||||||
<div className="text-muted-foreground hidden flex-1 text-sm lg:flex">
|
<div className="text-muted-foreground hidden flex-1 text-sm lg:flex">
|
||||||
{total > 0 && (
|
{total > 0 && <span>{tTable('totalRecords', { count: total })}</span>}
|
||||||
<span>
|
|
||||||
{tTable('totalRecords', { count: total })}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-full items-center gap-8 lg:w-fit">
|
<div className="flex w-full items-center gap-8 lg:w-fit">
|
||||||
<div className="hidden items-center gap-2 lg:flex">
|
<div className="hidden items-center gap-2 lg:flex">
|
||||||
|
Loading…
Reference in New Issue
Block a user