Files
HRM-System/resources/js/components/payment/paystack-payment-form.tsx
2026-04-13 08:16:56 +08:00

104 lines
2.6 KiB
TypeScript
Executable File

import { useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from '@/components/custom-toast';
import { usePaymentProcessor } from '@/hooks/usePaymentProcessor';
interface PaystackPaymentFormProps {
planId: number;
planPrice: number;
couponCode: string;
billingCycle: string;
paystackKey: string;
currency: string;
onSuccess: () => void;
onCancel: () => void;
}
export function PaystackPaymentForm({
planId,
planPrice,
couponCode,
billingCycle,
paystackKey,
currency,
onSuccess,
onCancel
}: PaystackPaymentFormProps) {
const { t } = useTranslation();
const initialized = useRef(false);
const { processPayment } = usePaymentProcessor({
onSuccess,
onError: (error) => toast.error(error)
});
useEffect(() => {
if (!paystackKey || initialized.current) return;
const script = document.createElement('script');
script.src = 'https://js.paystack.co/v1/inline.js';
script.async = true;
script.onload = () => {
initialized.current = true;
// Hide parent modal temporarily
const modalBackdrop = document.querySelector('[data-radix-dialog-overlay]');
if (modalBackdrop) {
(modalBackdrop as HTMLElement).style.display = 'none';
}
const handler = window.PaystackPop.setup({
key: paystackKey,
email: 'user@example.com', // Should be dynamic
amount: Math.round(Number(planPrice) * 100), // Convert to kobo as integer
currency: currency.toUpperCase(),
callback: function(response: any) {
// Restore modal backdrop
if (modalBackdrop) {
(modalBackdrop as HTMLElement).style.display = '';
}
processPayment('paystack', {
planId,
billingCycle,
couponCode,
payment_id: response.reference,
});
},
onClose: function() {
// Restore modal backdrop
if (modalBackdrop) {
(modalBackdrop as HTMLElement).style.display = '';
}
onCancel();
}
});
handler.openIframe();
};
document.head.appendChild(script);
return () => {
if (document.head.contains(script)) {
document.head.removeChild(script);
}
};
}, [paystackKey, planId, billingCycle, couponCode, currency]);
if (!paystackKey) {
return <div className="p-4 text-center text-red-500">{t('Paystack not configured')}</div>;
}
return (
<div className="p-4 text-center">
<p>{t('Redirecting to Paystack...')}</p>
</div>
);
}
declare global {
interface Window {
PaystackPop?: any;
}
}