feat: require compliance confirmation for paid features
Gate payment, redemption, subscription, and invitation reward flows behind an audited compliance acknowledgement.
This commit is contained in:
+3
-1
@@ -35,7 +35,7 @@ interface DataTableRowActionsProps {
|
||||
|
||||
export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
||||
const { t } = useTranslation()
|
||||
const { setOpen, setCurrentRow } = useSubscriptions()
|
||||
const { setOpen, setCurrentRow, complianceConfirmed } = useSubscriptions()
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
@@ -46,6 +46,7 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align='end'>
|
||||
<DropdownMenuItem
|
||||
disabled={!complianceConfirmed}
|
||||
onClick={() => {
|
||||
setCurrentRow(row.original)
|
||||
setOpen('update')
|
||||
@@ -55,6 +56,7 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
||||
{t('Edit')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
disabled={!complianceConfirmed}
|
||||
onClick={() => {
|
||||
setCurrentRow(row.original)
|
||||
setOpen('toggle-status')
|
||||
|
||||
+6
-2
@@ -23,10 +23,14 @@ import { useSubscriptions } from './subscriptions-provider'
|
||||
|
||||
export function SubscriptionsPrimaryButtons() {
|
||||
const { t } = useTranslation()
|
||||
const { setOpen } = useSubscriptions()
|
||||
const { setOpen, complianceConfirmed } = useSubscriptions()
|
||||
return (
|
||||
<div className='flex gap-2'>
|
||||
<Button size='sm' onClick={() => setOpen('create')}>
|
||||
<Button
|
||||
size='sm'
|
||||
onClick={() => setOpen('create')}
|
||||
disabled={!complianceConfirmed}
|
||||
>
|
||||
<Plus className='h-4 w-4' />
|
||||
{t('Create Plan')}
|
||||
</Button>
|
||||
|
||||
@@ -18,8 +18,14 @@ For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import React, { useState } from 'react'
|
||||
import useDialogState from '@/hooks/use-dialog'
|
||||
import {
|
||||
getOptionValue,
|
||||
useSystemOptions,
|
||||
} from '@/features/system-settings/hooks/use-system-options'
|
||||
import { type PlanRecord, type SubscriptionsDialogType } from '../types'
|
||||
|
||||
const CURRENT_COMPLIANCE_TERMS_VERSION = 'v1'
|
||||
|
||||
type SubscriptionsContextType = {
|
||||
open: SubscriptionsDialogType | null
|
||||
setOpen: (str: SubscriptionsDialogType | null) => void
|
||||
@@ -27,6 +33,7 @@ type SubscriptionsContextType = {
|
||||
setCurrentRow: React.Dispatch<React.SetStateAction<PlanRecord | null>>
|
||||
refreshTrigger: number
|
||||
triggerRefresh: () => void
|
||||
complianceConfirmed: boolean
|
||||
}
|
||||
|
||||
const SubscriptionsContext =
|
||||
@@ -40,6 +47,15 @@ export function SubscriptionsProvider({
|
||||
const [open, setOpen] = useDialogState<SubscriptionsDialogType>(null)
|
||||
const [currentRow, setCurrentRow] = useState<PlanRecord | null>(null)
|
||||
const [refreshTrigger, setRefreshTrigger] = useState(0)
|
||||
const { data } = useSystemOptions()
|
||||
const complianceOptions = getOptionValue(data?.data, {
|
||||
'payment_setting.compliance_confirmed': false,
|
||||
'payment_setting.compliance_terms_version': '',
|
||||
})
|
||||
const complianceConfirmed =
|
||||
complianceOptions['payment_setting.compliance_confirmed'] &&
|
||||
complianceOptions['payment_setting.compliance_terms_version'] ===
|
||||
CURRENT_COMPLIANCE_TERMS_VERSION
|
||||
|
||||
const triggerRefresh = () => setRefreshTrigger((prev) => prev + 1)
|
||||
|
||||
@@ -52,6 +68,7 @@ export function SubscriptionsProvider({
|
||||
setCurrentRow,
|
||||
refreshTrigger,
|
||||
triggerRefresh,
|
||||
complianceConfirmed,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
+25
-3
@@ -22,13 +22,18 @@ import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { SectionPageLayout } from '@/components/layout'
|
||||
import { SubscriptionsDialogs } from './components/subscriptions-dialogs'
|
||||
import { SubscriptionsPrimaryButtons } from './components/subscriptions-primary-buttons'
|
||||
import { SubscriptionsProvider } from './components/subscriptions-provider'
|
||||
import {
|
||||
SubscriptionsProvider,
|
||||
useSubscriptions,
|
||||
} from './components/subscriptions-provider'
|
||||
import { SubscriptionsTable } from './components/subscriptions-table'
|
||||
|
||||
export function Subscriptions() {
|
||||
function SubscriptionsContent() {
|
||||
const { t } = useTranslation()
|
||||
const { complianceConfirmed } = useSubscriptions()
|
||||
|
||||
return (
|
||||
<SubscriptionsProvider>
|
||||
<>
|
||||
<SectionPageLayout>
|
||||
<SectionPageLayout.Title>
|
||||
{t('Subscription Management')}
|
||||
@@ -50,11 +55,28 @@ export function Subscriptions() {
|
||||
</div>
|
||||
</SectionPageLayout.Actions>
|
||||
<SectionPageLayout.Content>
|
||||
{!complianceConfirmed ? (
|
||||
<Alert variant='destructive' className='mb-4'>
|
||||
<AlertDescription>
|
||||
{t(
|
||||
'Subscription plan creation and changes are locked until the administrator confirms compliance terms in Payment Gateway settings.'
|
||||
)}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
<SubscriptionsTable />
|
||||
</SectionPageLayout.Content>
|
||||
</SectionPageLayout>
|
||||
|
||||
<SubscriptionsDialogs />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function Subscriptions() {
|
||||
return (
|
||||
<SubscriptionsProvider>
|
||||
<SubscriptionsContent />
|
||||
</SubscriptionsProvider>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user