From 3955dab014f31a2218c8061890553b9d66e3290b Mon Sep 17 00:00:00 2001 From: estifanos Date: Wed, 26 Aug 2026 12:17:46 +0000 Subject: [PATCH] adding bypass payment --- .../endorsement/pages/EndorsementPage.tsx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/apps/portal/src/app/features/endorsement/pages/EndorsementPage.tsx b/apps/portal/src/app/features/endorsement/pages/EndorsementPage.tsx index a74a54be7..c6ce7252d 100644 --- a/apps/portal/src/app/features/endorsement/pages/EndorsementPage.tsx +++ b/apps/portal/src/app/features/endorsement/pages/EndorsementPage.tsx @@ -24,6 +24,7 @@ import { TERMINAL_STATUSES, extractErrorMessage, useLocalized, + useBypassPaymentMutation, useGetCertificateUrlMutation, useGetMyApplicationsQuery, useGetMyLicensesQuery, @@ -31,6 +32,7 @@ import { import { useCurrentProfile } from '@ema-platform/auth'; import { AdvancedTable, PageLoader, notify, useServerTable } from '@ema-platform/ui'; import { useDateDisplayer } from '@ema-platform/shared'; +import { useApplicationPayment } from '../../payments/hooks/useApplicationPayment'; import { endorsementColumns } from './columns'; // ENDORSEMENT_SEAFARER covers CoC and GOC together and is the only type new @@ -81,6 +83,8 @@ export function EndorsementPage() { const showDate = useDateDisplayer(); const localized = useLocalized(); const [getCertificateUrl] = useGetCertificateUrlMutation(); + const { pay, isPaying } = useApplicationPayment(); + const [bypassPayment, { isLoading: bypassing }] = useBypassPaymentMutation(); const issuedTable = useServerTable(); const registered = @@ -97,6 +101,22 @@ export function EndorsementPage() { ); const issuedPage = issuedTable.paginate(issued); + async function handleBypass(applicationId: string) { + try { + const result = await bypassPayment(applicationId).unwrap(); + notify.success( + result.certificateIssued + ? t('endorsement.bypassIssued', 'Payment bypassed — the endorsement has been issued.') + : t('endorsement.bypassOk', { + defaultValue: 'Payment bypassed — application is now {{status}}.', + status: result.status.replace(/_/g, ' ').toLowerCase(), + }), + ); + } catch (err) { + notify.error(extractErrorMessage(err, t('endorsement.bypassFailed', 'Bypass failed'))); + } + } + async function download(licenseId: string) { try { const result = await getCertificateUrl(licenseId).unwrap(); @@ -182,6 +202,36 @@ export function EndorsementPage() { {t(`applications.status.${app.status}`, STATUS_LABELS[app.status])} + {app.status === 'PAYMENT_PENDING' && ( + <> + + {/* ponytail: shown unconditionally for the testing + phase — the server still refuses it unless + ALLOW_PAYMENT_BYPASS is set and NODE_ENV is not + production. Re-gate on useGetPaymentCapabilitiesQuery + (like MyApplicationsPage) before prod. */} + + + )}