import React, { useState, useEffect, useRef } from 'react'; import { Card, CardBody, Col, Button, Row, CustomInput, Label } from 'reactstrap'; import Flex from '../common/Flex'; import FalconCardHeader from '../common/FalconCardHeader'; import { useTranslation } from 'react-i18next'; import iconPaymentMethodsGrid from '../../assets/img/icons/icon-payment-methods-grid.png'; import iconPaypalFull from '../../assets/img/icons/icon-paypal-full.png'; import { toast } from 'react-toastify'; import { updatePayment } from '../../helpers/rest'; import { useAuth } from '../../context/UserAuth'; import { getBillingInfo, updateBillingInfo, getUserDetail, getCountries } from '../../helpers/rest'; import { useForm, Controller } from 'react-hook-form'; import Select from 'react-select'; import { useResponsive } from '@farfetch/react-context-responsive'; const JKPaymentMethod = () => { const { t } = useTranslation('account'); const [billingInfo, setBillingInfo] = useState({}); const [hasStoredCreditCard, setHasStoredCreditCard] = useState(false); const [paymentMethod, setPaymentMethod] = useState('credit-card'); const { currentUser } = useAuth(); const [countries, setCountries] = useState([]); const labelClassName = 'ls text-600 font-weight-semi-bold mb-0'; const [submitting, setSubmitting] = useState(false); const [billingDataLoaded, setBillingDataLoaded] = useState(false); const [isCardValid, setIsCardValid] = useState(false); const { greaterThan } = useResponsive(); const elementsRef = useRef(null); const formRef = useRef(null); const recurlyConfigured = useRef(false); const paypal = useRef(null); const { register, control, handleSubmit, setValue, formState: { errors } } = useForm({ defaultValues: { first_name: '', last_name: '', address1: '', address2: '', city: '', state: '', zip: '', country: 'US', } }); useEffect(() => { if (currentUser) { populateUserData(); } }, [currentUser]); const populateUserData = async () => { const options = { id: currentUser.id }; try { const userResp = await getUserDetail(options); const userData = await userResp.json(); if (userData.has_recurly_account) { setHasStoredCreditCard(userData['has_stored_credit_card?']); await populateBillingAddress(); setBillingDataLoaded(true); } } catch (error) { console.error('Failed to get user details:', error); } }; const populateBillingAddress = async () => { try { const resp = await getBillingInfo(); const data = await resp.json(); const bi = data.billing_info; setBillingInfo(bi); } catch (error) { console.error('Failed to get billing info:', error); } }; useEffect(() => { if (currentUser) { fetchCountries(); } }, [currentUser]); const fetchCountries = () => { getCountries() .then(response => { if (response.ok) { return response.json(); } }) .then(data => { setCountries(data.countriesx); }) .catch(error => console.log(error)); }; useEffect(() => { if (billingInfo) { setValue('first_name', billingInfo.first_name || ''); setValue('last_name', billingInfo.last_name || ''); setValue('address1', billingInfo.address1 || ''); setValue('address2', billingInfo.address2 || ''); setValue('city', billingInfo.city || ''); setValue('state', billingInfo.state || ''); setValue('zip', billingInfo.zip || ''); setValue('country', billingInfo.country || 'US'); } }, [billingInfo, setValue]); const handleCountryChange = selectedOption => { setValue('country', selectedOption.value); }; useEffect(() => { if (!window.recurly) return; if (recurlyConfigured.current) return; const interval = setInterval(() => { const container = document.querySelector('#recurly-elements'); console.log('Checking for Recurly Elements container:', container); if (container && window.recurly) { console.log('Initializing Recurly Elements...'); window.recurly.configure({ publicKey: process.env.REACT_APP_RECURLY_PUBLIC_API_KEY }); const elements = window.recurly.Elements(); const cardElement = elements.CardElement(); cardElement.attach('#recurly-elements'); cardElement.on('change', (event) => { if (event.complete) { setIsCardValid(true); } else if (event.error) { setIsCardValid(false); } else { setIsCardValid(false); } }); //then load paypal: const paypalInst = window.recurly.PayPal({ braintree: { clientAuthorization: process.env.REACT_APP_BRAINTREE_TOKEN } }) paypal.current = paypalInst; paypal.current.on('error', onPayPalError); paypal.current.on('token', onPayPalToken); elementsRef.current = elements; recurlyConfigured.current = true; clearInterval(interval); } }, 100); return () => clearInterval(interval); }, []); const onPayPalError = (error) => { console.error('PayPal Error:', error); toast.error('PayPal Error: ' + (error.message || t('payment_method.alerts.try_again'))); setSubmitting(false); } const onPayPalToken = (token) => { handleUpdatePayment(token); } const handleUpdatePayment = (token) => { updatePayment({ recurly_token: token.id }).then((response) => { setHasStoredCreditCard(true); toast.success(t('payment_method.alerts.payment_method_updated')); }).catch((error) => { console.error('Error updating payment with PayPal token:', error); if (error.response && error.response.data && error.response.data.message) { toast.error(error.response.data.message); } else { console.error('Error updating payment with PayPal token:', error); toast.error(t('payment_method.alerts.card_update_error')); } }).finally(() => { setSubmitting(false); }); }; const onSubmit = async (data) => { //first update billing address setSubmitting(true); const resp = await updateBillingInfo(data) if (!resp.ok) { setSubmitting(false); const errorData = await resp.json(); console.error('Error updating billing info:', errorData); toast.error(errorData.message || t('payment_method.alerts.billing_update_error')); return; } if (paymentMethod === 'paypal') { handoverToPaypal(); return; } else { if (!elementsRef.current) { console.error('Recurly elementsRef.current is not ready'); setSubmitting(false); return; } if (!formRef.current) { console.error('formRef.current is not ready'); setSubmitting(false); return; } // if (!isCardValid) { // console.error('Card is not valid'); // toast.error(t('payment_method.validations.card.invalid')); // setSubmitting(false); // return; // } window.recurly.token(elementsRef.current, formRef.current, (err, token) => { if (err) { console.error('Recurly token error:', err); toast.error(err.message || t('payment_method.alerts.card_processing_error')); setSubmitting(false); } else { console.log('Recurly token:', token.id); // send token.id to backend handleUpdatePayment(token); } }); } }; const handoverToPaypal = () => { // Handover to Paypal setSubmitting(true); paypal.current.start() }; return (
{hasStoredCreditCard ? ( {t('payment_method.help_text_has_card')} ) : ( {t('payment_method.help_text_no_card')} )} {t('payment_method.help_text')}
{errors.first_name && (
{errors.first_name.message}
)}
{errors.last_name && (
{errors.last_name.message}
)}
{errors.address1 && (
{errors.address1.message}
)}
{errors.address2 && (
{errors.address2.message}
)}
{errors.city && (
{errors.city.message}
)}
{errors.state && (
{errors.state.message}
)}
{errors.zip && (
{errors.zip.message}
)}
{ const country = countries.find(country => country.countrycode === value); if (!country) { return ( { return { value: c.countrycode, label: c.countryname }; })} /> ); }} /> {errors.country && (
{errors.country.message}
)}
{t('payment_method.credit_card')} } id="credit-card" value="credit-card" checked={paymentMethod === 'credit-card'} onChange={({ target }) => setPaymentMethod(target.value)} type="radio" />
{!isCardValid && errors.recurly && (
{errors.recurly.message}
)}
{t('payment_method.we_accept')}

} id="paypal" value="paypal" checked={paymentMethod === 'paypal'} onChange={({ target }) => setPaymentMethod(target.value)} type="radio" />

{t('payment_method.aggreement.text1')} {t('payment_method.aggreement.text2')} {t('payment_method.aggreement.text3')}{' '}
{t('payment_method.aggreement.terms_of_service')}

); }; export default JKPaymentMethod;