mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +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. */
|
||||
export function inFlightColumns(
|
||||
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>[] {
|
||||
return [
|
||||
{
|
||||
@@ -38,15 +45,49 @@ export function inFlightColumns(
|
||||
},
|
||||
{
|
||||
header: t('applications.table.progress'),
|
||||
size: 140,
|
||||
cell: ({ row }) => (
|
||||
<Progress
|
||||
value={STATUS_PROGRESS[row.original.status]}
|
||||
color={STATUS_COLORS[row.original.status]}
|
||||
size="sm"
|
||||
radius="xl"
|
||||
/>
|
||||
),
|
||||
size: 300,
|
||||
cell: ({ row }) => {
|
||||
const app = row.original;
|
||||
return (
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
<Progress
|
||||
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: '',
|
||||
|
||||
@@ -30,11 +30,16 @@ import {
|
||||
import { StatusBadge, AdvancedTable } from '@ema-platform/ui';
|
||||
import { inFlightColumns } from '../inFlightColumns';
|
||||
import {
|
||||
extractErrorMessage,
|
||||
TERMINAL_STATUSES,
|
||||
useApiMutation,
|
||||
useBypassPaymentMutation,
|
||||
useGetMyApplicationsQuery,
|
||||
useGetPaymentCapabilitiesQuery,
|
||||
} from '@ema-platform/api';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { authStorage } from '@ema-platform/auth';
|
||||
import { useApplicationPayment } from '../../payments/hooks/useApplicationPayment';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -132,6 +137,9 @@ export function VesselRegistrationPage() {
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
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 [registration, setRegistration] = useState<VesselRegistration | null>(null);
|
||||
const [fetchTrigger] = useApiMutation<VesselRegistration>();
|
||||
@@ -155,9 +163,33 @@ export function VesselRegistrationPage() {
|
||||
!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, {
|
||||
onOpen: (app) =>
|
||||
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)'
|
||||
|
||||
Reference in New Issue
Block a user