import React, { FormEvent, useEffect, useState } from 'react'; import Select from 'react-select'; import { useTranslation } from 'react-i18next'; import { GatewayFormProps } from '../abstract-payment-modal'; import LocalPaymentAPI from '../../../api/local-payment'; import FormatLib from '../../../lib/format'; import SettingAPI from '../../../api/setting'; import { CardPaymentModal } from '../card-payment-modal'; import { PaymentSchedule } from '../../../models/payment-schedule'; import { HtmlTranslate } from '../../base/html-translate'; import CheckoutAPI from '../../../api/checkout'; const ALL_SCHEDULE_METHODS = ['card', 'check', 'transfer'] as const; type scheduleMethod = typeof ALL_SCHEDULE_METHODS[number]; /** * Option format, expected by react-select * @see https://github.com/JedWatson/react-select */ type selectOption = { value: scheduleMethod, label: string }; /** * A form component to ask for confirmation before cashing a payment directly at the FabLab's reception. * This is intended for use by privileged users. * The form validation button must be created elsewhere, using the attribute form={formId}. */ export const LocalPaymentForm: React.FC = ({ onSubmit, onSuccess, onError, children, className, paymentSchedule, cart, updateCart, customer, operator, formId, order }) => { const { t } = useTranslation('admin'); const [method, setMethod] = useState('check'); const [onlinePaymentModal, setOnlinePaymentModal] = useState(false); useEffect(() => { setMethod(cart.payment_method || 'check'); }, [cart]); /** * Open/closes the online payment modal, used to collect card credentials when paying the payment schedule by card. */ const toggleOnlinePaymentModal = (): void => { setOnlinePaymentModal(!onlinePaymentModal); }; /** * Convert all payement methods for schedules to the react-select format */ const buildMethodOptions = (): Array => { return ALL_SCHEDULE_METHODS.map(i => methodToOption(i)); }; /** * Convert the given payment-method to the react-select format */ const methodToOption = (value: scheduleMethod): selectOption => { if (!value) return { value, label: '' }; return { value, label: t(`app.admin.local_payment_form.method_${value}`) }; }; /** * Callback triggered when the user selects a payment method for the current payment schedule. */ const handleUpdateMethod = (option: selectOption) => { updateCart(Object.assign({}, cart, { payment_method: option.value })); setMethod(option.value); }; /** * Handle the submission of the form. It will process the local payment. */ const handleSubmit = async (event: FormEvent): Promise => { event.preventDefault(); onSubmit(); if (paymentSchedule && method === 'card') { // check that the online payment is active try { const online = await SettingAPI.get('online_payment_module'); if (online.value !== 'true') { return onError(t('app.admin.local_payment_form.online_payment_disabled')); } return toggleOnlinePaymentModal(); } catch (e) { onError(e); } } try { let res; if (order) { res = await CheckoutAPI.payment(order); res = res.order; } else { res = await LocalPaymentAPI.confirmPayment(cart); } onSuccess(res); } catch (e) { onError(e); } }; /** * Callback triggered after a successful payment by online card for a schedule. */ const afterCreatePaymentSchedule = (document: PaymentSchedule) => { toggleOnlinePaymentModal(); onSuccess(document); }; /** * Generally, this form component is only shown to admins or to managers when they book for someone else. * If this is not the case, then it is shown to validate a free (or prepaid by wallet) cart. * This function will return `true` in the later case. */ const isFreeOfCharge = (): boolean => { return (customer.id === operator.id); }; /** * Get the type of the main item in the cart compile */ const mainItemType = (): string => { if (order) { return ''; } return Object.keys(cart.items[0])[0]; }; return (
{!paymentSchedule && !isFreeOfCharge() &&

{t('app.admin.local_payment_form.about_to_cash')}

} {!paymentSchedule && isFreeOfCharge() &&

{t('app.admin.local_payment_form.about_to_confirm', { ITEM: mainItemType() })}

} {paymentSchedule &&