mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
Merge branch 'RegisterWizard' of https://github.com/abouolia/Ratteb into RegisterWizard
This commit is contained in:
41
client/src/common/subscriptionModels.js
Normal file
41
client/src/common/subscriptionModels.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
export const plans = [
|
||||||
|
{
|
||||||
|
name: 'basic',
|
||||||
|
description: [
|
||||||
|
'Sales/purchases module.',
|
||||||
|
'Expense module.',
|
||||||
|
'Inventory module.',
|
||||||
|
'Unlimited status pages.',
|
||||||
|
'Unlimited status pages.',
|
||||||
|
],
|
||||||
|
price: '1200',
|
||||||
|
slug: 'free',
|
||||||
|
currency: 'LYD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pro',
|
||||||
|
description: [
|
||||||
|
'Sales/purchases module.',
|
||||||
|
'Expense module.',
|
||||||
|
'Inventory module.',
|
||||||
|
'Unlimited status pages.',
|
||||||
|
'Unlimited status pages.',
|
||||||
|
],
|
||||||
|
price: '1200',
|
||||||
|
slug: 'free',
|
||||||
|
currency: 'LYD',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const paymentmethod = [
|
||||||
|
{
|
||||||
|
period: 'monthly',
|
||||||
|
price: '1200',
|
||||||
|
currency: 'LYD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
period: 'yearly',
|
||||||
|
price: '1200',
|
||||||
|
currency: 'LYD',
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -12,6 +12,7 @@ import ErrorMessage from 'components/ErrorMessage';
|
|||||||
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
import withDashboardActions from 'containers/Dashboard/withDashboardActions';
|
||||||
import { MeteredBillingTabs, PaymentMethodTabs } from './SubscriptionTabs';
|
import { MeteredBillingTabs, PaymentMethodTabs } from './SubscriptionTabs';
|
||||||
import withBillingActions from './withBillingActions';
|
import withBillingActions from './withBillingActions';
|
||||||
|
import withRegisterOrganizationActions from 'containers/Authentication/withRegisterOrganizationActions';
|
||||||
import { compose } from 'utils';
|
import { compose } from 'utils';
|
||||||
|
|
||||||
function BillingForm({
|
function BillingForm({
|
||||||
@@ -20,11 +21,14 @@ function BillingForm({
|
|||||||
|
|
||||||
//#withBillingActions
|
//#withBillingActions
|
||||||
requestSubmitBilling,
|
requestSubmitBilling,
|
||||||
|
|
||||||
|
//#withRegisterOrganizationActions
|
||||||
|
requestBuildTenant,
|
||||||
}) {
|
}) {
|
||||||
// const defaultPlan = useMemo(() => ({
|
// const defaultPlan = useMemo(() => ({
|
||||||
// plan_slug: [
|
// plan_slug: [
|
||||||
// { id: 0, name: 'Basic', value: 'basic' },
|
// { name: 'Basic', value: 'basic' },
|
||||||
// { id: 0, name: 'Pro', value: 'pro' },
|
// { name: 'Pro', value: 'pro' },
|
||||||
// ],
|
// ],
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
@@ -39,12 +43,14 @@ function BillingForm({
|
|||||||
.required()
|
.required()
|
||||||
.label(formatMessage({ id: 'plan_slug' })),
|
.label(formatMessage({ id: 'plan_slug' })),
|
||||||
license_code: Yup.string().trim(),
|
license_code: Yup.string().trim(),
|
||||||
|
period: Yup.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialValues = useMemo(
|
const initialValues = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
plan_slug: 'basic',
|
plan_slug: 'basic',
|
||||||
license_code: '',
|
license_code: '',
|
||||||
|
period: '',
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
@@ -58,13 +64,15 @@ function BillingForm({
|
|||||||
onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
|
onSubmit: (values, { setSubmitting, resetForm, setErrors }) => {
|
||||||
requestSubmitBilling(values)
|
requestSubmitBilling(values)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
AppToaster.show({
|
requestBuildTenant().then(() => {
|
||||||
message: formatMessage({
|
setSubmitting(false);
|
||||||
id: 'the_biling_has_been_successfully_created',
|
|
||||||
}),
|
|
||||||
intent: Intent.SUCCESS,
|
|
||||||
});
|
});
|
||||||
setSubmitting(false);
|
// AppToaster.show({
|
||||||
|
// message: formatMessage({
|
||||||
|
// id: 'the_biling_has_been_successfully_created',
|
||||||
|
// }),
|
||||||
|
// intent: Intent.SUCCESS,
|
||||||
|
// });
|
||||||
})
|
})
|
||||||
.catch((errors) => {
|
.catch((errors) => {
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
@@ -90,4 +98,8 @@ function BillingForm({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default compose(withDashboardActions, withBillingActions)(BillingForm);
|
export default compose(
|
||||||
|
withDashboardActions,
|
||||||
|
withRegisterOrganizationActions,
|
||||||
|
withBillingActions,
|
||||||
|
)(BillingForm);
|
||||||
|
|||||||
@@ -1,163 +1,15 @@
|
|||||||
import React, {
|
import React from 'react';
|
||||||
useState,
|
import BillingPlans from 'containers/Subscriptions/billingPlans';
|
||||||
useMemo,
|
import BillingPeriods from 'containers/Subscriptions/billingPeriods';
|
||||||
useCallback,
|
import { BillingPaymentmethod } from 'containers/Subscriptions/billingPaymentmethod';
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
} from 'react';
|
|
||||||
import { FormattedMessage as T, useIntl } from 'react-intl';
|
|
||||||
import { PaymentMethodTabs } from './SubscriptionTabs';
|
|
||||||
|
|
||||||
function BillingTab({ formik }) {
|
function BillingTab({ formik }) {
|
||||||
const [plan, setPlan] = useState();
|
console.log(formik.values, 'val');
|
||||||
const planRef = useRef(null);
|
|
||||||
const billingRef = useRef(null);
|
|
||||||
|
|
||||||
const handlePlan = () => {
|
|
||||||
const plans = planRef.current.querySelectorAll('a');
|
|
||||||
const planSelected = planRef.current.querySelector('.plan-selected');
|
|
||||||
|
|
||||||
plans.forEach((el) => {
|
|
||||||
el.addEventListener('click', () => {
|
|
||||||
planSelected.classList.remove('plan-selected');
|
|
||||||
el.classList.add('plan-selected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBilling = () => {
|
|
||||||
const billingPriod = billingRef.current.querySelectorAll('a');
|
|
||||||
const billingSelected = billingRef.current.querySelector(
|
|
||||||
'.billing-selected',
|
|
||||||
);
|
|
||||||
billingPriod.forEach((el) => {
|
|
||||||
el.addEventListener('click', () => {
|
|
||||||
billingSelected.classList.remove('billing-selected');
|
|
||||||
el.classList.add('billing-selected');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handlePlan();
|
|
||||||
handleBilling();
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<section>
|
<BillingPlans title={'a_select_a_plan'} formik={formik} />
|
||||||
<h1 className={'bg-title'}>
|
<BillingPeriods title={'b_choose_your_billing'} formik={formik} />
|
||||||
<T id={'a_select_a_plan'} />
|
<BillingPaymentmethod title={'c_payment_methods'} formik={formik} />
|
||||||
</h1>
|
|
||||||
<p className={'bg-message '}>
|
|
||||||
<T id={'please_enter_your_preferred_payment_method'} />
|
|
||||||
</p>
|
|
||||||
<div className={'billing-form__plan-container'} ref={planRef}>
|
|
||||||
<a
|
|
||||||
id={'basic-plan'}
|
|
||||||
className={`plan-wrapper plan-selected`}
|
|
||||||
onClick={() =>
|
|
||||||
setPlan({ ...formik.setFieldValue('plan_slug', 'basic') })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className={'plan-header'}>
|
|
||||||
<div className={'plan-name'}>
|
|
||||||
<T id={'Basic'} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={'plan-description'}>
|
|
||||||
<ul>
|
|
||||||
<li>Sales/purchases module.</li>
|
|
||||||
<li>Expense module.</li>
|
|
||||||
<li>Inventory module.</li>
|
|
||||||
<li>Unlimited status pages.</li>
|
|
||||||
<li>Unlimited status pages.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className={'plan-price'}>
|
|
||||||
<span className={'amount'}>1200 LYD</span>
|
|
||||||
<span className={'period'}>
|
|
||||||
<T id={'year_per'} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
id={'pro-plan'}
|
|
||||||
className={`plan-wrapper`}
|
|
||||||
onClick={() =>
|
|
||||||
setPlan({ ...formik.setFieldValue('plan_slug', 'pro') })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div className={'plan-header'}>
|
|
||||||
<div className={'plan-name'}>
|
|
||||||
<T id={'pro'} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className={'plan-description'}>
|
|
||||||
<ul>
|
|
||||||
<li>Sales/purchases module.</li>
|
|
||||||
<li>Expense module.</li>
|
|
||||||
<li>Inventory module.</li>
|
|
||||||
<li>Unlimited status pages.</li>
|
|
||||||
<li>Unlimited status pages.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className={'plan-price'}>
|
|
||||||
<span className={'amount'}>1200 LYD</span>
|
|
||||||
<span className={'period'}>
|
|
||||||
<T id={'year_per'} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h1 className={'bg-title'}>
|
|
||||||
<T id={'b_choose_your_billing'} />
|
|
||||||
</h1>
|
|
||||||
<p className={'bg-message'}>
|
|
||||||
<T id={'please_enter_your_preferred_payment_method'} />
|
|
||||||
</p>
|
|
||||||
<div className={'payment-method-continer'} ref={billingRef}>
|
|
||||||
<a
|
|
||||||
href={'#!'}
|
|
||||||
formik={formik}
|
|
||||||
id={'monthly'}
|
|
||||||
className={'period-container billing-selected'}
|
|
||||||
>
|
|
||||||
<span className={'bg-period'}>
|
|
||||||
<T id={'monthly'} />
|
|
||||||
</span>
|
|
||||||
<div className={'plan-price'}>
|
|
||||||
<span className={'amount'}>1200 LYD</span>
|
|
||||||
<span className={'period'}>
|
|
||||||
<T id={'year'} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a href={'#!'} id={'yearly'} className={'period-container'}>
|
|
||||||
<span className={'bg-period'}>
|
|
||||||
<T id={'yearly'} />
|
|
||||||
</span>
|
|
||||||
<div className={'plan-price'}>
|
|
||||||
<span className={'amount'}>1200 LYD</span>
|
|
||||||
<span className={'period'}>
|
|
||||||
<T id={'year'} />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h1 className={'bg-title'}>
|
|
||||||
<T id={'c_payment_methods'} />
|
|
||||||
</h1>
|
|
||||||
<p className={'bg-message'}>
|
|
||||||
<T id={'please_enter_your_preferred_payment_method'} />
|
|
||||||
</p>
|
|
||||||
<PaymentMethodTabs formik={formik} />
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
17
client/src/containers/Subscriptions/billingPaymentmethod.js
Normal file
17
client/src/containers/Subscriptions/billingPaymentmethod.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
|
import { PaymentMethodTabs } from './SubscriptionTabs';
|
||||||
|
|
||||||
|
export const BillingPaymentmethod = ({ formik, title }) => {
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<h1 className={'bg-title'}>
|
||||||
|
<T id={title} />
|
||||||
|
</h1>
|
||||||
|
<p className={'bg-message'}>
|
||||||
|
<T id={'please_enter_your_preferred_payment_method'} />
|
||||||
|
</p>
|
||||||
|
<PaymentMethodTabs formik={formik} />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
68
client/src/containers/Subscriptions/billingPeriods.js
Normal file
68
client/src/containers/Subscriptions/billingPeriods.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { paymentmethod } from 'common/subscriptionModels';
|
||||||
|
|
||||||
|
function BillingPeriod({ price, period, currency, onSelected, selected }) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={'#!'}
|
||||||
|
id={'monthly'}
|
||||||
|
className={`period-container ${classNames({
|
||||||
|
'billing-selected': selected,
|
||||||
|
})} `}
|
||||||
|
>
|
||||||
|
<span className={'bg-period'}>
|
||||||
|
<T id={period} />
|
||||||
|
</span>
|
||||||
|
<div className={'plan-price'}>
|
||||||
|
<span className={'amount'}>
|
||||||
|
{price} {currency}
|
||||||
|
</span>
|
||||||
|
<span className={'period'}>
|
||||||
|
<T id={'year'} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function BillingPeriods({ formik, title, selected = 1 }) {
|
||||||
|
const billingRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const billingPriod = billingRef.current.querySelectorAll('a');
|
||||||
|
const billingSelected = billingRef.current.querySelector(
|
||||||
|
'.billing-selected',
|
||||||
|
);
|
||||||
|
billingPriod.forEach((el) => {
|
||||||
|
el.addEventListener('click', () => {
|
||||||
|
billingSelected.classList.remove('billing-selected');
|
||||||
|
el.classList.add('billing-selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<h1 className={'bg-title'}>
|
||||||
|
<T id={title} />
|
||||||
|
</h1>
|
||||||
|
<p className={'bg-message'}>
|
||||||
|
<T id={'please_enter_your_preferred_payment_method'} />
|
||||||
|
</p>
|
||||||
|
<div className={'payment-method-continer'} ref={billingRef}>
|
||||||
|
{paymentmethod.map((pay, index) => (
|
||||||
|
<BillingPeriod
|
||||||
|
period={pay.period}
|
||||||
|
price={pay.price}
|
||||||
|
currency={pay.currency}
|
||||||
|
onSelected={()=>formik.setFieldValue('period', pay.period)}
|
||||||
|
selected={selected == index + 1}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BillingPeriods;
|
||||||
89
client/src/containers/Subscriptions/billingPlans.js
Normal file
89
client/src/containers/Subscriptions/billingPlans.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import { FormattedMessage as T, useIntl } from 'react-intl';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { plans } from 'common/subscriptionModels';
|
||||||
|
|
||||||
|
function BillingPlan({
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
price,
|
||||||
|
slug,
|
||||||
|
currency,
|
||||||
|
onSelected,
|
||||||
|
selected,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
id={'basic-plan'}
|
||||||
|
className={`plan-wrapper ${classNames({
|
||||||
|
'plan-selected': selected,
|
||||||
|
})} `}
|
||||||
|
onClick={() => onSelected(slug)}
|
||||||
|
>
|
||||||
|
<div className={'plan-header'}>
|
||||||
|
<div className={'plan-name'}>
|
||||||
|
<T id={name} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={'plan-description'}>
|
||||||
|
<ul>
|
||||||
|
{description.map((desc, index) => (
|
||||||
|
<li>{desc}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className={'plan-price'}>
|
||||||
|
<span className={'amount'}>
|
||||||
|
{' '}
|
||||||
|
{price} {currency}
|
||||||
|
</span>
|
||||||
|
<span className={'period'}>
|
||||||
|
<T id={'year_per'} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function BillingPlans({ formik, title, selected = 1 }) {
|
||||||
|
const planRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const plans = planRef.current.querySelectorAll('a');
|
||||||
|
const planSelected = planRef.current.querySelector('.plan-selected');
|
||||||
|
|
||||||
|
plans.forEach((el) => {
|
||||||
|
el.addEventListener('click', () => {
|
||||||
|
planSelected.classList.remove('plan-selected');
|
||||||
|
el.classList.add('plan-selected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<h1 className={'bg-title'}>
|
||||||
|
<T id={title} />
|
||||||
|
</h1>
|
||||||
|
<p className={'bg-message '}>
|
||||||
|
<T id={'please_enter_your_preferred_payment_method'} />
|
||||||
|
</p>
|
||||||
|
<div className={'billing-form__plan-container'} ref={planRef}>
|
||||||
|
{plans.map((plan, index) => (
|
||||||
|
<BillingPlan
|
||||||
|
name={plan.name}
|
||||||
|
description={plan.description}
|
||||||
|
slug={plan.slug}
|
||||||
|
price={plan.price}
|
||||||
|
currency={plan.currency}
|
||||||
|
onSelected={() => formik.setFieldValue('plan_slug', plan.name)}
|
||||||
|
selected={selected == index + 1}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BillingPlans;
|
||||||
|
|
||||||
Reference in New Issue
Block a user