mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-08 04:15:44 +00:00
feat: add payment and bypass actions to the in-flight vessel registration application table
This commit is contained in:
@@ -12,7 +12,14 @@ import {
|
|||||||
/** Columns for the applicant's in-flight vessel registration applications. */
|
/** Columns for the applicant's in-flight vessel registration applications. */
|
||||||
export function inFlightColumns(
|
export function inFlightColumns(
|
||||||
t: TFunction,
|
t: TFunction,
|
||||||
deps: { onOpen: (app: LicenseApplication) => void },
|
deps: {
|
||||||
|
onOpen: (app: LicenseApplication) => void;
|
||||||
|
onPay: (app: LicenseApplication) => void;
|
||||||
|
onBypass: (app: LicenseApplication) => void;
|
||||||
|
isPaying: boolean;
|
||||||
|
bypassEnabled: boolean;
|
||||||
|
bypassing: boolean;
|
||||||
|
},
|
||||||
): AdvancedColumn<LicenseApplication>[] {
|
): AdvancedColumn<LicenseApplication>[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -38,15 +45,49 @@ export function inFlightColumns(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('applications.table.progress'),
|
header: t('applications.table.progress'),
|
||||||
size: 140,
|
size: 300,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => {
|
||||||
<Progress
|
const app = row.original;
|
||||||
value={STATUS_PROGRESS[row.original.status]}
|
return (
|
||||||
color={STATUS_COLORS[row.original.status]}
|
<Group gap="xs" wrap="nowrap">
|
||||||
size="sm"
|
<Progress
|
||||||
radius="xl"
|
value={STATUS_PROGRESS[app.status]}
|
||||||
/>
|
color={STATUS_COLORS[app.status]}
|
||||||
),
|
size="sm"
|
||||||
|
radius="xl"
|
||||||
|
style={{ flex: 1, minWidth: 60 }}
|
||||||
|
/>
|
||||||
|
{/* The fee stops the registration dead, so the payment action sits
|
||||||
|
on the bar rather than being hidden behind View. */}
|
||||||
|
{app.status === 'PAYMENT_PENDING' && (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
size="compact-sm"
|
||||||
|
color="yellow"
|
||||||
|
loading={deps.isPaying}
|
||||||
|
onClick={() => deps.onPay(app)}
|
||||||
|
>
|
||||||
|
{t('applications.actions.pay', {
|
||||||
|
amount: Number(app.feeAmount ?? 0).toLocaleString(),
|
||||||
|
currency: app.feeCurrency,
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
{deps.bypassEnabled && (
|
||||||
|
<Button
|
||||||
|
size="compact-sm"
|
||||||
|
variant="default"
|
||||||
|
loading={deps.bypassing}
|
||||||
|
onClick={() => deps.onBypass(app)}
|
||||||
|
title="Testing only — marks the fee paid"
|
||||||
|
>
|
||||||
|
{t('applications.actions.bypass')}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: '',
|
header: '',
|
||||||
|
|||||||
@@ -30,11 +30,16 @@ import {
|
|||||||
import { StatusBadge, AdvancedTable } from '@ema-platform/ui';
|
import { StatusBadge, AdvancedTable } from '@ema-platform/ui';
|
||||||
import { inFlightColumns } from '../inFlightColumns';
|
import { inFlightColumns } from '../inFlightColumns';
|
||||||
import {
|
import {
|
||||||
|
extractErrorMessage,
|
||||||
TERMINAL_STATUSES,
|
TERMINAL_STATUSES,
|
||||||
useApiMutation,
|
useApiMutation,
|
||||||
|
useBypassPaymentMutation,
|
||||||
useGetMyApplicationsQuery,
|
useGetMyApplicationsQuery,
|
||||||
|
useGetPaymentCapabilitiesQuery,
|
||||||
} from '@ema-platform/api';
|
} from '@ema-platform/api';
|
||||||
|
import { notifications } from '@mantine/notifications';
|
||||||
import { authStorage } from '@ema-platform/auth';
|
import { authStorage } from '@ema-platform/auth';
|
||||||
|
import { useApplicationPayment } from '../../payments/hooks/useApplicationPayment';
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Types
|
// Types
|
||||||
@@ -132,6 +137,9 @@ export function VesselRegistrationPage() {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { data: applications, isFetching, refetch } = useGetMyApplicationsQuery();
|
const { data: applications, isFetching, refetch } = useGetMyApplicationsQuery();
|
||||||
|
const { pay, isPaying } = useApplicationPayment();
|
||||||
|
const { data: capabilities } = useGetPaymentCapabilitiesQuery();
|
||||||
|
const [bypassPayment, { isLoading: bypassing }] = useBypassPaymentMutation();
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const [registration, setRegistration] = useState<VesselRegistration | null>(null);
|
const [registration, setRegistration] = useState<VesselRegistration | null>(null);
|
||||||
const [fetchTrigger] = useApiMutation<VesselRegistration>();
|
const [fetchTrigger] = useApiMutation<VesselRegistration>();
|
||||||
@@ -155,9 +163,33 @@ export function VesselRegistrationPage() {
|
|||||||
!TERMINAL_STATUSES.includes(app.status),
|
!TERMINAL_STATUSES.includes(app.status),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function handleBypass(applicationId: string) {
|
||||||
|
try {
|
||||||
|
const result = await bypassPayment(applicationId).unwrap();
|
||||||
|
notifications.show({
|
||||||
|
color: 'teal',
|
||||||
|
title: 'Payment bypassed',
|
||||||
|
message: `Application is now ${result.status.replace(/_/g, ' ').toLowerCase()}.`,
|
||||||
|
});
|
||||||
|
refetch();
|
||||||
|
} catch (err) {
|
||||||
|
notifications.show({
|
||||||
|
color: 'red',
|
||||||
|
title: 'Bypass failed',
|
||||||
|
message: extractErrorMessage(err),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const columns = inFlightColumns(t, {
|
const columns = inFlightColumns(t, {
|
||||||
onOpen: (app) =>
|
onOpen: (app) =>
|
||||||
navigate(`/licensing/${REGISTRATION_TYPE_KEY}/applications/${app.id}`),
|
navigate(`/licensing/${REGISTRATION_TYPE_KEY}/applications/${app.id}`),
|
||||||
|
// Paying leaves the SPA for Telebirr — a provider hand-off, not a route change.
|
||||||
|
onPay: (app) => pay(app.id),
|
||||||
|
onBypass: (app) => handleBypass(app.id),
|
||||||
|
isPaying,
|
||||||
|
bypassEnabled: capabilities?.bypassEnabled ?? false,
|
||||||
|
bypassing,
|
||||||
});
|
});
|
||||||
|
|
||||||
const certs = registration?.category === 'Sea-going Vessel (International)'
|
const certs = registration?.category === 'Sea-going Vessel (International)'
|
||||||
|
|||||||
Reference in New Issue
Block a user