/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
import { type ColumnDef } from '@tanstack/react-table'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { BadgeCell } from '@/components/data-table'
import { GroupBadge } from '@/components/group-badge'
import { StatusBadge } from '@/components/status-badge'
import { TableId } from '@/components/table-id'
import { formatQuota } from '@/lib/format'
import { formatDuration, formatResetPeriod } from '../lib'
import type { PlanRecord } from '../types'
import { DataTableRowActions } from './data-table-row-actions'
export function useSubscriptionsColumns(): ColumnDef[] {
const { t } = useTranslation()
return useMemo(
(): ColumnDef[] => [
{
accessorFn: (row) => row.plan.id,
id: 'id',
header: t('ID'),
meta: { mobileHidden: true },
cell: ({ row }) => ,
size: 60,
},
{
accessorFn: (row) => row.plan.title,
id: 'title',
header: t('Plan'),
meta: { mobileTitle: true },
cell: ({ row }) => {
const plan = row.original.plan
return (
{plan.title}
{plan.subtitle && (
{plan.subtitle}
)}
)
},
size: 200,
},
{
accessorFn: (row) => row.plan.price_amount,
id: 'price',
header: t('Price'),
cell: ({ row }) => (
${Number(row.original.plan.price_amount || 0).toFixed(2)}
),
size: 100,
},
{
id: 'duration',
header: t('Validity'),
cell: ({ row }) => (
{formatDuration(row.original.plan, t)}
),
size: 100,
},
{
id: 'reset',
header: t('Quota Reset'),
meta: { mobileHidden: true },
cell: ({ row }) => (
{formatResetPeriod(row.original.plan, t)}
),
size: 100,
},
{
accessorFn: (row) => row.plan.sort_order,
id: 'sort_order',
header: t('Priority'),
meta: { mobileHidden: true },
cell: ({ row }) => (
{row.original.plan.sort_order}
),
size: 100,
},
{
accessorFn: (row) => row.plan.enabled,
id: 'enabled',
header: t('Status'),
meta: { mobileBadge: true },
cell: ({ row }) =>
row.original.plan.enabled ? (
) : (
),
size: 80,
},
{
id: 'payment',
header: t('Payment Channel'),
meta: { mobileHidden: true },
cell: ({ row }) => {
const plan = row.original.plan
return (
{plan.stripe_price_id && (
)}
{plan.creem_product_id && (
)}
{plan.waffo_pancake_product_id && (
)}
)
},
size: 140,
},
{
id: 'total_amount',
header: t('Plan Quota'),
meta: { mobileHidden: true },
cell: ({ row }) => {
const total = Number(row.original.plan.total_amount || 0)
return (
{total > 0 ? formatQuota(total) : t('Unlimited')}
)
},
size: 150,
},
{
id: 'upgrade_group',
header: t('Upgrade Group'),
meta: { mobileHidden: true },
cell: ({ row }) => {
const group = row.original.plan.upgrade_group
if (!group) {
return (
{t('No Upgrade')}
)
}
return (
)
},
size: 120,
},
{
id: 'actions',
header: () => t('Actions'),
cell: ({ row }) => ,
meta: { pinned: 'right' as const },
},
],
[t]
)
}