mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
proceed with payment on subscription renewal
This commit is contained in:
parent
4e4849e7bc
commit
336a4b789c
@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Subscription, SubscriptionPaymentDetails } from '../../models/subscription';
|
||||
import { Subscription } from '../../models/subscription';
|
||||
import { FabModal, ModalSize } from '../base/fab-modal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FabAlert } from '../base/fab-alert';
|
||||
@ -8,12 +8,16 @@ import FormatLib from '../../lib/format';
|
||||
import { Loader } from '../base/loader';
|
||||
import { react2angular } from 'react2angular';
|
||||
import { IApplication } from '../../models/application';
|
||||
import LocalPaymentAPI from '../../api/local-payment';
|
||||
import { PaymentMethod, ShoppingCart } from '../../models/payment';
|
||||
import moment from 'moment';
|
||||
import { SelectSchedule } from '../payment-schedule/select-schedule';
|
||||
import SubscriptionAPI from '../../api/subscription';
|
||||
import PriceAPI from '../../api/price';
|
||||
import { ComputePriceResult } from '../../models/price';
|
||||
import { PaymentScheduleSummary } from '../payment-schedule/payment-schedule-summary';
|
||||
import { PaymentSchedule } from '../../models/payment-schedule';
|
||||
import { LocalPaymentModal } from '../payment/local-payment/local-payment-modal';
|
||||
import { User } from '../../models/user';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -21,7 +25,8 @@ interface RenewModalProps {
|
||||
isOpen: boolean,
|
||||
toggleModal: () => void,
|
||||
subscription?: Subscription,
|
||||
customerId: number,
|
||||
customer: User,
|
||||
operator: User,
|
||||
onSuccess: (message: string, newExpirationDate: Date) => void,
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
@ -29,12 +34,13 @@ interface RenewModalProps {
|
||||
/**
|
||||
* Modal dialog shown to renew the current subscription of a customer, for free
|
||||
*/
|
||||
const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscription, customerId, onError, onSuccess }) => {
|
||||
const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscription, customer, operator, onError, onSuccess }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const [expirationDate, setExpirationDate] = useState<Date>(new Date());
|
||||
const [localPaymentModal, setLocalPaymentModal] = useState<boolean>(false);
|
||||
const [cart, setCart] = useState<ShoppingCart>(null);
|
||||
const [price, setPrice] = useState<ComputePriceResult>(null);
|
||||
const [scheduleRequired, setScheduleRequired] = useState<boolean>(false);
|
||||
|
||||
// on init, we compute the new expiration date
|
||||
@ -49,6 +55,31 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
||||
.catch(err => onError(err));
|
||||
}, []);
|
||||
|
||||
// when the payment schedule is toggled (requested/ignored), we update the cart accordingly
|
||||
useEffect(() => {
|
||||
if (!subscription) return;
|
||||
|
||||
setCart({
|
||||
customer_id: customer.id,
|
||||
items: [{
|
||||
subscription: {
|
||||
plan_id: subscription.plan.id
|
||||
}
|
||||
}],
|
||||
payment_method: PaymentMethod.Other,
|
||||
payment_schedule: scheduleRequired
|
||||
});
|
||||
}, [scheduleRequired]);
|
||||
|
||||
// when the cart is updated, re-compute the price and the payment schedule
|
||||
useEffect(() => {
|
||||
if (!cart) return;
|
||||
|
||||
PriceAPI.compute(cart)
|
||||
.then(res => setPrice(res))
|
||||
.catch(err => onError(err));
|
||||
}, [cart]);
|
||||
|
||||
/**
|
||||
* Return the formatted localized date for the given date
|
||||
*/
|
||||
@ -57,24 +88,18 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when the user validates the renew of the subscription
|
||||
* Callback triggered when the payment of the subscription renewal was successful
|
||||
*/
|
||||
const handleConfirmRenew = (): void => {
|
||||
LocalPaymentAPI.confirmPayment({
|
||||
customer_id: customerId,
|
||||
payment_method: PaymentMethod.Other,
|
||||
items: [
|
||||
{
|
||||
subscription: {
|
||||
plan_id: subscription.plan_id
|
||||
// start_at: subscription.expired_at
|
||||
}
|
||||
}
|
||||
]
|
||||
}).then(() => {
|
||||
onSuccess(t('app.admin.renew_subscription_modal.renew_success'), expirationDate);
|
||||
toggleModal();
|
||||
}).catch(err => onError(err));
|
||||
const onPaymentSuccess = (): void => {
|
||||
onSuccess(t('app.admin.renew_subscription_modal.renew_success'), expirationDate);
|
||||
toggleModal();
|
||||
};
|
||||
|
||||
/**
|
||||
* Open/closes the local payment modal
|
||||
*/
|
||||
const toggleLocalPaymentModal = (): void => {
|
||||
setLocalPaymentModal(!localPaymentModal);
|
||||
};
|
||||
|
||||
// we do not render the modal if the subscription was not provided
|
||||
@ -87,7 +112,7 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
||||
className="renew-modal"
|
||||
title={t('app.admin.renew_subscription_modal.renew_subscription')}
|
||||
confirmButton={t('app.admin.renew_subscription_modal.renew')}
|
||||
onConfirm={handleConfirmRenew}
|
||||
onConfirm={toggleLocalPaymentModal}
|
||||
closeButton>
|
||||
<FabAlert level="danger" className="conditions">
|
||||
<p>{t('app.admin.renew_subscription_modal.renew_subscription_info')}</p>
|
||||
@ -110,18 +135,31 @@ const RenewModal: React.FC<RenewModalProps> = ({ isOpen, toggleModal, subscripti
|
||||
</form>
|
||||
<div className="payment">
|
||||
<SelectSchedule show selected={scheduleRequired} onChange={setScheduleRequired} />
|
||||
{price?.schedule && <PaymentScheduleSummary schedule={price.schedule as PaymentSchedule} />}
|
||||
{price && !price?.schedule && <div className="one-go-payment">
|
||||
<h4>{t('app.admin.renew_subscription_modal.pay_in_one_go')}</h4>
|
||||
<span>{FormatLib.price(price.price)}</span>
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
<LocalPaymentModal isOpen={localPaymentModal}
|
||||
toggleModal={toggleLocalPaymentModal}
|
||||
afterSuccess={onPaymentSuccess}
|
||||
onError={onError}
|
||||
cart={cart}
|
||||
currentUser={operator}
|
||||
customer={customer}
|
||||
schedule={price?.schedule as PaymentSchedule} />
|
||||
</FabModal>
|
||||
);
|
||||
};
|
||||
|
||||
const RenewModalWrapper: React.FC<RenewModalProps> = ({ toggleModal, subscription, customerId, isOpen, onSuccess, onError }) => {
|
||||
const RenewModalWrapper: React.FC<RenewModalProps> = ({ toggleModal, subscription, customer, operator, isOpen, onSuccess, onError }) => {
|
||||
return (
|
||||
<Loader>
|
||||
<RenewModal toggleModal={toggleModal} subscription={subscription} customerId={customerId} isOpen={isOpen} onError={onError} onSuccess={onSuccess} />
|
||||
<RenewModal toggleModal={toggleModal} subscription={subscription} customer={customer} operator={operator} isOpen={isOpen} onError={onError} onSuccess={onSuccess} />
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
||||
Application.Components.component('renewModal', react2angular(RenewModalWrapper, ['toggleModal', 'subscription', 'customerId', 'isOpen', 'onError', 'onSuccess']));
|
||||
Application.Components.component('renewModal', react2angular(RenewModalWrapper, ['toggleModal', 'subscription', 'customer', 'operator', 'isOpen', 'onError', 'onSuccess']));
|
||||
|
@ -18,6 +18,10 @@
|
||||
border-radius: 2px;
|
||||
padding: 10px;
|
||||
width: 50%;
|
||||
|
||||
.one-go-payment {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,8 @@
|
||||
<renew-modal is-open="isOpenRenewModal"
|
||||
toggle-modal="toggleRenewModal"
|
||||
subscription="subscription"
|
||||
customer-id="user.id"
|
||||
customer="user"
|
||||
operator="currentUser"
|
||||
on-error="onError"
|
||||
on-success="onExtendSuccess">
|
||||
</renew-modal>
|
||||
|
@ -77,8 +77,9 @@ class CartService
|
||||
index = cart_items[:items].index { |item| ['subscription', :subscription].include?(item.keys.first) }
|
||||
if cart_items[:items][index][:subscription][:plan_id]
|
||||
new_plan_being_bought = true
|
||||
subscription = cart_items[:items][index][:subscription].to_object
|
||||
Plan.find(cart_items[:items][index][:subscription][:plan_id])
|
||||
plan = Plan.find(cart_items[:items][index][:subscription][:plan_id])
|
||||
subscription = CartItem::Subscription.new(plan, @customer).to_object
|
||||
plan
|
||||
end
|
||||
elsif @customer.subscribed_plan
|
||||
subscription = @customer.subscription unless @customer.subscription.expired_at < DateTime.current
|
||||
|
@ -922,6 +922,7 @@ en:
|
||||
payment_schedule_check: "The previous subscription was charged by check through a payment schedule, this one will be charged the same way. Before confirming please ensure you have all the checks to collect all the monthly payments."
|
||||
one_payment_card: "The previous subscription was charged by card through a single payment, this one will be charged the same way. The payment will be charged right now."
|
||||
one_payment_check: "The previous subscription was charged by check through a single payment, this one will be charged the same way. Before confirming please ensure you have collected the payment."
|
||||
pay_in_one_go: "Pay in one go"
|
||||
renew: "Renew"
|
||||
renew_success: "The subscription was successfully renewed"
|
||||
#add a new administrator to the platform
|
||||
|
@ -417,7 +417,7 @@ en:
|
||||
NUMBER_monthly_payment_of_AMOUNT: "{NUMBER} monthly {NUMBER, plural, =1{payment} other{payments}} of {AMOUNT}"
|
||||
first_debit: "First debit on the day of the order."
|
||||
debit: "Debit on the day of the order."
|
||||
view_full_schedule: "View the complete payement schedule"
|
||||
view_full_schedule: "View the complete payment schedule"
|
||||
confirm_and_pay: "Confirm and pay"
|
||||
you_have_settled_the_following_TYPE: "You have settled the following {TYPE, select, Machine{machine slots} Training{training} other{elements}}:"
|
||||
you_have_settled_a_: "You have settled a"
|
||||
|
Loading…
x
Reference in New Issue
Block a user