parent
ee95d07dfc
commit
dbb5c4a520
|
|
@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
const JKModalDialog = (args) => {
|
||||
const { show, title, children, onToggle, showFooter, ...rest } = args;
|
||||
const { show, title, children, onToggle, showFooter, modalFooterButtons, ...rest } = args;
|
||||
const [modal, setModal] = useState(show);
|
||||
|
||||
const toggle = () => {
|
||||
|
|
@ -24,7 +24,16 @@ const JKModalDialog = (args) => {
|
|||
<ModalBody>{children}</ModalBody>
|
||||
{showFooter && (
|
||||
<ModalFooter>
|
||||
<Button onClick={toggle}>{t('close', { ns: 'common' })}</Button>
|
||||
{modalFooterButtons ? (
|
||||
<>
|
||||
{modalFooterButtons.map((button, index) => (
|
||||
<Button key={index} onClick={button.onClick} color={button.color} disabled={button.disabled}>
|
||||
{button.text}
|
||||
</Button>
|
||||
))}
|
||||
</>
|
||||
) : (<Button onClick={toggle}>{t('close', { ns: 'common' })}</Button>) }
|
||||
|
||||
</ModalFooter>
|
||||
)}
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import JKMusicSessionsLobby from '../page/JKMusicSessionsLobby';
|
|||
|
||||
import JKEditProfile from '../page/JKEditProfile';
|
||||
import JKEditAccount from '../page/JKEditAccount';
|
||||
import JKAccountSubscription from '../page/JKAccountSubscription';
|
||||
|
||||
|
||||
//import loadable from '@loadable/component';
|
||||
|
|
@ -261,6 +262,7 @@ function JKDashboardMain() {
|
|||
<PrivateRoute path="/notifications" component={JKNotifications} />
|
||||
<PrivateRoute path="/profile" component={JKEditProfile} />
|
||||
<PrivateRoute path="/account/identity" component={JKEditAccount} />
|
||||
<PrivateRoute path="/account/subscription" component={JKAccountSubscription} />
|
||||
{/*Redirect*/}
|
||||
<Redirect to="/errors/404" />
|
||||
</Switch>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Row, Col, Card, CardBody } from 'reactstrap';
|
||||
import FalconCardHeader from '../common/FalconCardHeader';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import JKSubscriptionPlan from '../profile/JKSubscriptionPlan';
|
||||
import JKSubscriptionPlaytime from '../profile/JKSubscriptionPlaytime';
|
||||
|
||||
import { getSubscription } from '../../helpers/rest';
|
||||
|
||||
const JKAccountSubscription = () => {
|
||||
const { t } = useTranslation('account');
|
||||
const [userPlan, setUserPlan] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
getSubscription()
|
||||
.then(resp => resp.json())
|
||||
.then(data => {
|
||||
setUserPlan(data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('subscriptionError', error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const getDisplayName = planCode => {
|
||||
if (planCode == '') {
|
||||
planCode = null;
|
||||
}
|
||||
const plan = window.gon.global.subscription_codes.find(plan => plan.id === planCode);
|
||||
if (plan) {
|
||||
return plan.name;
|
||||
}
|
||||
return `Unknown plan code=${planCode}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FalconCardHeader title={t('subscription.page_title')} titleClass="font-weight-bold" />
|
||||
<CardBody className="pt-3" style={{ backgroundColor: '#edf2f9' }}>
|
||||
{userPlan ? (
|
||||
<Row>
|
||||
<Col className="mb-2">
|
||||
<JKSubscriptionPlan userPlan={userPlan} setUserPlan={setUserPlan} getDisplayName={getDisplayName} />
|
||||
</Col>
|
||||
<Col>
|
||||
<JKSubscriptionPlaytime userPlan={userPlan} getDisplayName={getDisplayName} />
|
||||
</Col>
|
||||
<Col />
|
||||
</Row>
|
||||
) : 'Loading...' }
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default JKAccountSubscription;
|
||||
|
|
@ -20,7 +20,7 @@ const JKEditAccount = () => {
|
|||
<FalconCardHeader title={t('identity.page_title')} titleClass="font-weight-bold" />
|
||||
<CardBody className="pt-3" style={{ backgroundColor: '#edf2f9' }}>
|
||||
<Row>
|
||||
<Col>
|
||||
<Col className='mb-2'>
|
||||
<JKEditEmail setAlert={setAlertText} toggleAlert={toggleAlert} />
|
||||
</Col>
|
||||
<Col>
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ const JKEditPassword = ({ setAlert, toggleAlert }) => {
|
|||
<CardHeader>
|
||||
<h5>Password</h5>
|
||||
</CardHeader>
|
||||
<CardBody className="bg-light" style={{ minHeight: 300 }}>
|
||||
<CardBody className="bg-light" style={{ minHeight: 300, minWidth: 280 }}>
|
||||
<small>
|
||||
{t('identity.password_form.help_text')}
|
||||
</small>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, CardHeader, CardBody, Form, FormGroup, Label } from 'reactstrap';
|
||||
import Select from 'react-select';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { useForm, Controller, set } from 'react-hook-form';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import JKModalDialog from '../common/JKModalDialog';
|
||||
|
||||
import { getSubscription, changeSubscription } from '../../helpers/rest';
|
||||
|
||||
function JKSubscriptionPlan({ userPlan, setUserPlan, getDisplayName }) {
|
||||
const { t } = useTranslation('account');
|
||||
|
||||
const [plans, setPlans] = useState([]);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [alertText, setAlertText] = useState('');
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const toggleAlert = () => setShowAlert(!showAlert);
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
formState: { errors },
|
||||
setError,
|
||||
setValue,
|
||||
getValues
|
||||
} = useForm({
|
||||
defaultValues: {
|
||||
plan_code: ''
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (userPlan) {
|
||||
setValue('plan_code', userPlan.desired_plan_code);
|
||||
}
|
||||
}, [userPlan]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (window.gon) {
|
||||
const monthly = [{ value: 'monthly', isDisabled: true, label: '-------- MONTHLY PLANS --------' }];
|
||||
const yearly = [{ value: 'yearly', isDisabled: true, label: '-------- YEARLY PLANS --------' }];
|
||||
window.gon.global.subscription_codes.forEach(plan => {
|
||||
if (plan.cycle === 'month') {
|
||||
monthly.push({ value: plan.id || '', label: `${plan.name} (${plan.price.toFixed(2)}/${plan.cycle})` });
|
||||
}
|
||||
if (plan.cycle === 'year') {
|
||||
yearly.push({ value: plan.id || '', label: `${plan.name} (${plan.price.toFixed(2)}/${plan.cycle})` });
|
||||
}
|
||||
});
|
||||
const all = [...monthly, ...yearly];
|
||||
setPlans(all);
|
||||
}
|
||||
}, [window.gon]);
|
||||
|
||||
const handleChange = selectedOption => {
|
||||
console.log('selectedOption', selectedOption);
|
||||
setError('plan_code', { type: 'manual', message: '' });
|
||||
setValue('plan_code', selectedOption.value);
|
||||
};
|
||||
|
||||
const getDisplayNamePrice = planCode => {
|
||||
if (planCode == '') {
|
||||
planCode = null;
|
||||
}
|
||||
const plan = window.gon.global.subscription_codes.find(plan => plan.id === planCode);
|
||||
if (plan) {
|
||||
return plan.price;
|
||||
}
|
||||
return `Unknown plan code=${planCode}`;
|
||||
};
|
||||
|
||||
const getDisplayCycle = planCode => {
|
||||
if (planCode == '') {
|
||||
planCode = null;
|
||||
}
|
||||
for (const subscriptionCode of window.gon.global.subscription_codes) {
|
||||
if (planCode === subscriptionCode.id) {
|
||||
if (subscriptionCode.cycle === 'year') {
|
||||
return 'annual';
|
||||
} else {
|
||||
return subscriptionCode.cycle + 'ly';
|
||||
}
|
||||
}
|
||||
}
|
||||
return `Unknown plan code=${planCode}`;
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
const planCode = getValues('plan_code');
|
||||
if (planCode === null) {
|
||||
setError('plan_code', {
|
||||
type: 'manual',
|
||||
message: t('subscription.current_plan.validations.subscription_plan.required')
|
||||
});
|
||||
setSubmitting(false);
|
||||
return;
|
||||
} else if (planCode === '') {
|
||||
setAlertText(t('subscription.alerts.changed_to_free_plan'));
|
||||
toggleAlert();
|
||||
} else {
|
||||
setAlertText(
|
||||
`You have selected the ${getDisplayName(planCode).toUpperCase()} ${getDisplayCycle(
|
||||
planCode
|
||||
).toUpperCase()} PLAN and will be charged US$${getDisplayNamePrice(planCode)}.`
|
||||
);
|
||||
toggleAlert();
|
||||
}
|
||||
};
|
||||
|
||||
const updateSubscription = () => {
|
||||
toggleAlert();
|
||||
setSubmitting(true);
|
||||
const planCode = getValues('plan_code');
|
||||
changeSubscription(planCode)
|
||||
.then(resp => {
|
||||
console.log('changeSubscription', resp);
|
||||
if (resp.ok) {
|
||||
getSubscription()
|
||||
.then(resp => resp.json())
|
||||
.then(data => {
|
||||
console.log('subscriptionData', data);
|
||||
setUserPlan(data);
|
||||
setValue('plan_code', data.desired_plan_code);
|
||||
toast.success(t('subscription.alerts.changed_plan_successfully'));
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('subscriptionError', error);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
setAlertText(`${t('subscription.alerts.failed_to_change_plan')}: ${error}`);
|
||||
console.log('changeSubscriptionError', error);
|
||||
setValue('plan_code', userPlan.desired_plan_code);
|
||||
})
|
||||
.finally(() => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
const cancelUpdateSubscription = () => {
|
||||
setValue('plan_code', userPlan.desired_plan_code);
|
||||
setSubmitting(false);
|
||||
toggleAlert();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h5>{t('subscription.current_plan.title')}</h5>
|
||||
</CardHeader>
|
||||
<CardBody className="bg-light" style={{ minHeight: 300, minWidth: 280 }}>
|
||||
<small>{t('subscription.current_plan.help_text')}</small>
|
||||
<Form
|
||||
className="mt-2"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
data-testid="edit_email_form"
|
||||
>
|
||||
{plans && userPlan && userPlan.plan_code && (
|
||||
<>
|
||||
<FormGroup>
|
||||
<Label for="plan_code">{t('subscription.current_plan.subscription_plan')}</Label>
|
||||
<Controller
|
||||
name="plan_code"
|
||||
control={control}
|
||||
render={({ field: { onChange, value } }) => {
|
||||
const plan = plans.find(plan => plan.value === value);
|
||||
if (!plan) {
|
||||
return <Select data-testid="countrySelect" onChange={handleChange} options={plans} />;
|
||||
}
|
||||
return (
|
||||
<Select data-testid="countrySelect" value={plan} onChange={handleChange} options={plans} />
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{errors.plan_code && <div className="text-danger">{errors.plan_code.message}</div>}
|
||||
</FormGroup>
|
||||
<div className="d-flex justify-content-end">
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
value={t('subscription.current_plan.submit')}
|
||||
disabled={submitting || [userPlan.desired_plan_code].includes(getValues('plan_code'))}
|
||||
data-testid="email_submit"
|
||||
/>
|
||||
<span className="ml-2">{submitting && <FontAwesomeIcon icon="spinner" />}</span>
|
||||
</div>
|
||||
<div className='mt-3'>
|
||||
<small>
|
||||
{ t('subscription.current_plan.notice.part1') }<a target='_blank' href="https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-">{ t('subscription.current_plan.notice.click_here') }</a>{ t('subscription.current_plan.notice.part2') }
|
||||
</small>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<JKModalDialog
|
||||
show={showAlert}
|
||||
onToggle={toggleAlert}
|
||||
title={t('subscription.alerts.title')}
|
||||
data-testid="subscription-plan-update-notification"
|
||||
size="md"
|
||||
modalFooterButtons={[
|
||||
{
|
||||
text: t('cancel', { ns: 'common' }),
|
||||
color: 'secondary',
|
||||
onClick: cancelUpdateSubscription,
|
||||
disabled: submitting
|
||||
},
|
||||
{
|
||||
text: t('ok', { ns: 'common' }),
|
||||
color: 'primary',
|
||||
onClick: updateSubscription,
|
||||
disabled: submitting
|
||||
}
|
||||
]}
|
||||
>
|
||||
{alertText}
|
||||
</JKModalDialog>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default JKSubscriptionPlan;
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { Card, CardHeader, CardBody, Label } from 'reactstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { formatDateShort } from '../../helpers/utils';
|
||||
import { get } from 'react-hook-form';
|
||||
|
||||
function JKSubscriptionPlaytime({ userPlan, getDisplayName }) {
|
||||
const { t } = useTranslation('account');
|
||||
|
||||
const [explanation, setExplanation] = useState('');
|
||||
const [warning, setWarning] = useState('');
|
||||
const [billingAddendum, setBillingAddendum] = useState(''); // [TODO: addendum to the warning message about billing, if needed]
|
||||
const showPaymentInfoRef = useRef(false);
|
||||
|
||||
const displayTime = until_time => {
|
||||
if (until_time < 0) return 'no time';
|
||||
|
||||
const untilTime = getTimeRemaining(until_time * 1000);
|
||||
|
||||
let timeString = '';
|
||||
if (untilTime.days !== 0) timeString += `${untilTime.days} days, `;
|
||||
if (untilTime.hours !== 0 || timeString.length > 0) timeString += `${untilTime.hours} hours, `;
|
||||
if (untilTime.minutes !== 0 || timeString.length > 0) timeString += `${untilTime.minutes} minutes `;
|
||||
if (timeString === '') timeString = 'now!';
|
||||
|
||||
return timeString;
|
||||
};
|
||||
|
||||
const getTimeRemaining = t => {
|
||||
if (t < 0) t = -t;
|
||||
|
||||
const seconds = Math.floor((t / 1000) % 60);
|
||||
const minutes = Math.floor((t / 1000 / 60) % 60);
|
||||
const hours = Math.floor((t / (1000 * 60 * 60)) % 24);
|
||||
const days = Math.floor(t / (1000 * 60 * 60 * 24));
|
||||
|
||||
return {
|
||||
total: t,
|
||||
days: days,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
seconds: seconds
|
||||
};
|
||||
};
|
||||
|
||||
const getDisplayNamePrice = planCode => {
|
||||
if (planCode == '') {
|
||||
planCode = null;
|
||||
}
|
||||
const plan = window.gon.global.subscription_codes.find(plan => plan.id === planCode);
|
||||
if (plan) {
|
||||
return plan.price;
|
||||
}
|
||||
return `Unknown plan code=${planCode}`;
|
||||
};
|
||||
|
||||
const getDisplayCycle = planCode => {
|
||||
if (planCode == '') {
|
||||
planCode = null;
|
||||
}
|
||||
for (const subscriptionCode of window.gon.global.subscription_codes) {
|
||||
if (planCode === subscriptionCode.id) {
|
||||
if (subscriptionCode.cycle === 'year') {
|
||||
return 'annual';
|
||||
} else {
|
||||
return subscriptionCode.cycle + 'ly';
|
||||
}
|
||||
}
|
||||
}
|
||||
return `Unknown plan code=${planCode}`;
|
||||
};
|
||||
|
||||
const planNameWithCycle = planCode => {
|
||||
return getDisplayName(planCode) + ' (' + getDisplayCycle(planCode) + ')';
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (userPlan) {
|
||||
let expl,
|
||||
note,
|
||||
warning,
|
||||
billingAddendumTxt,
|
||||
playtimeTxt = '';
|
||||
const adminOverride = userPlan.admin_override_plan_code;
|
||||
const inTrail = userPlan.in_trail;
|
||||
const hasBillingInfo = userPlan.has_billing_info;
|
||||
const effectivePlanName = planNameWithCycle(userPlan.plan_code);
|
||||
const desiredPlanCode = userPlan.desired_plan_code;
|
||||
const desiredPlanName = planNameWithCycle(desiredPlanCode);
|
||||
const hasPendingSubscription = userPlan.subscription.pending_subscription;
|
||||
const canceledSubscription = userPlan.subscription.remaining_billing_cycles === 0;
|
||||
|
||||
if (adminOverride) {
|
||||
expl = `You have a <strong>${effectivePlanName}</strong> account until your gifted plan ends ${formatDateShort(
|
||||
userPlan.admin_override_ends_at
|
||||
)}.`;
|
||||
} else if (inTrail) {
|
||||
if (desiredPlanCode) {
|
||||
if (hasBillingInfo) {
|
||||
note = `Billing starts for the <strong>${desiredPlanName}</strong> plan after the trial ends.`;
|
||||
} else {
|
||||
warning = `You will drop to the <strong>free plan</strong> after the trial ends because you have not yet entered payment info.`;
|
||||
showPaymentInfoRef.current = true;
|
||||
}
|
||||
} else {
|
||||
if (hasBillingInfo) {
|
||||
warning = `You will drop to the <strong>free plan</strong> after the trial ends because you have not selected a plan.`;
|
||||
} else {
|
||||
warning = `You will drop to the <strong>free plan</strong> after the trial ends because you have not yet entered payment info or selected a plan.`;
|
||||
showPaymentInfoRef.current = true;
|
||||
}
|
||||
}
|
||||
expl = `You have a <strong>${effectivePlanName}</strong> account until your trial ends <strong>${formatDateShort(
|
||||
userPlan.trial_ends_at
|
||||
)}</strong>. ${note}`;
|
||||
} else {
|
||||
// NOT admin override and NOT in trial
|
||||
if (desiredPlanCode && !userPlan.plan_code && !hasBillingInfo) {
|
||||
expl = `You have successfully upgraded your plan to the <strong>${desiredPlanName}</strong> level, thank you!`;
|
||||
warning = `For this plan to take effect, you must provide a payment method (e.g. a credit card), for the monthly subscription charge. Please click the Update Payment Method button to do this now.`;
|
||||
//show_payment_info = true
|
||||
showPaymentInfoRef.current = true;
|
||||
} else {
|
||||
if (desiredPlanCode) {
|
||||
if (!hasBillingInfo) {
|
||||
//show_payment_info = true
|
||||
showPaymentInfoRef.current = true;
|
||||
expl = `You have successfully upgraded your plan to the ${desiredPlanName} level, thank you`;
|
||||
warning = `However, you must provide a payment method (e.g. a credit card), for the monthly subscription charge. Please click the Update Payment Method button to do this now.`;
|
||||
} else {
|
||||
expl = `You are currently on the <strong>${effectivePlanName}</strong> level, thank you!`;
|
||||
}
|
||||
} else {
|
||||
//free plan situation - not much to go on about
|
||||
expl = `You are currently on the <strong>${effectivePlanName}</strong> plan.`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setExplanation(expl);
|
||||
setWarning(warning);
|
||||
|
||||
//billingAddendum
|
||||
if (hasPendingSubscription) {
|
||||
if (userPlan.subscription.plan.plan_code !== userPlan.plan_code) {
|
||||
billingAddendumTxt = ` You have paid only for the <strong>${planNameWithCycle(
|
||||
userPlan.subscription.plan.plan_code
|
||||
)}</strong> level for the current billing cycle, so there will be a change to the <strong>${this.planNameWithCycle(
|
||||
this.props.subscription.subscription.pending_subscription.plan.plan_code
|
||||
)}</strong> level on the next billing cycle.`;
|
||||
} else {
|
||||
billingAddendumTxt = ` And your plan and billing will switch to the <strong>${planNameWithCycle(
|
||||
userPlan.subscription.pending_subscription.plan.plan_code
|
||||
)}</strong> level on the next billing cycle.`;
|
||||
}
|
||||
} else if (canceledSubscription && userPlan.desired_plan_code === null && userPlan.plan_code !== null) {
|
||||
billingAddendumTxt = ` However, your cancelled <strong>${effectivePlanName}</strong> plan is still active until the end of the billing cycle. You will be billed a final time at the <strong>${planNameWithCycle(
|
||||
userPlan.subscription.plan.plan_code
|
||||
)}</strong> at end of this billing cycle.`;
|
||||
} else {
|
||||
billingAddendumTxt = '';
|
||||
}
|
||||
setBillingAddendum(billingAddendumTxt);
|
||||
}
|
||||
}, [userPlan]);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<h5>{t('subscription.play_time.title')}</h5>
|
||||
</CardHeader>
|
||||
<CardBody className="bg-light" style={{ minHeight: 300, minWidth: 280 }}>
|
||||
<div>
|
||||
{userPlan && userPlan.subscription_rules.remaining_month_play_time ? (
|
||||
<div className="play-time">
|
||||
<p>
|
||||
You have <strong>{planNameWithCycle(userPlan.subscription_rules.remaining_month_play_time)}</strong> remaining
|
||||
this month. Only the time you spend in a session with 2 or more people uses your session play time.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="play-time">
|
||||
<p>You have unlimited play time.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-3">
|
||||
<small>
|
||||
{explanation && (
|
||||
<div className="alert alert-info">
|
||||
<span dangerouslySetInnerHTML={{ __html: explanation }} />
|
||||
<span dangerouslySetInnerHTML={{ __html: billingAddendum }} />
|
||||
</div>
|
||||
)}
|
||||
{warning && <div className="alert alert-warning" dangerouslySetInnerHTML={{ __html: warning }} />}
|
||||
</small>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default JKSubscriptionPlaytime;
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { error } from 'is_js';
|
||||
import apiFetch from './apiFetch';
|
||||
|
||||
export const getMusicians = page => {
|
||||
|
|
@ -277,4 +278,26 @@ export const postUserAppInteraction = (userId, options) => {
|
|||
.then(response => resolve(response))
|
||||
.catch(error => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export const getSubscription = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch('/recurly/get_subscription')
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export const changeSubscription = (plan_code) => {
|
||||
const options = {plan_code}
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch('/recurly/change_subscription', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(options)
|
||||
})
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error));
|
||||
})
|
||||
}
|
||||
|
|
@ -234,4 +234,16 @@ export const currencyFormat = (num) => {
|
|||
return new Intl.NumberFormat('en-US',
|
||||
{ style: 'currency', currency: 'USD' }
|
||||
).format(num);
|
||||
}
|
||||
|
||||
const days = new Array("Sun", "Mon", "Tue",
|
||||
"Wed", "Thu", "Fri", "Sat");
|
||||
|
||||
const months = new Array("January", "February", "March",
|
||||
"April", "May", "June", "July", "August", "September",
|
||||
"October", "November", "December");
|
||||
|
||||
export const formatDateShort = (dateString) => {
|
||||
const date = dateString instanceof Date ? dateString : new Date(dateString);
|
||||
return months[date.getMonth()] + ' ' + date.getDate() + ', ' + date.getFullYear();
|
||||
}
|
||||
|
|
@ -54,5 +54,35 @@
|
|||
}
|
||||
|
||||
|
||||
},
|
||||
"subscription": {
|
||||
"page_title": "Subscription",
|
||||
"current_plan": {
|
||||
"title": "Current Plan",
|
||||
"help_text": "Your JamKazam subscription plan is currently set to the plan displayed below. To change your plan, click the subscription plan box below, select a new plan from the list, and then click the Save Plan button.",
|
||||
"subscription_plan": "Subscription Plan",
|
||||
"validations": {
|
||||
"subscription_plan": {
|
||||
"required": "Subscription plan is required"
|
||||
}
|
||||
},
|
||||
"submit": "Save Plan",
|
||||
"notice": {
|
||||
"part1": "To compare the features available for different subscription plans ",
|
||||
"click_here": "click here",
|
||||
"part2": " to view a help article on our available plans."
|
||||
|
||||
}
|
||||
},
|
||||
"play_time": {
|
||||
"title": "Play Time",
|
||||
"description": ""
|
||||
},
|
||||
"alerts": {
|
||||
"title": "Subscription Plan Update",
|
||||
"changed_to_free_plan": "You have chosen to go back down to the FREE PLAN. Your subscription will be canceled, and you will keep your plan until the end of the current billing cycle.",
|
||||
"failed_to_change_plan": "Failed to update subscription plan. Please try again later. Please contact support@jamkazam.com if you continue to have problems.",
|
||||
"changed_plan_successfully": "You have successfully updated your subscription plan."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@
|
|||
"actions": "Actions",
|
||||
"no_records": "No Records!",
|
||||
"close": "Close",
|
||||
"cancel": "Cancel",
|
||||
"ok": "OK",
|
||||
"navigation": {
|
||||
"home": "Home",
|
||||
"friends": "Friends",
|
||||
|
|
|
|||
|
|
@ -54,5 +54,35 @@
|
|||
}
|
||||
|
||||
|
||||
},
|
||||
"subscription": {
|
||||
"page_title": "Suscripción",
|
||||
"current_plan": {
|
||||
"title": "plan actual",
|
||||
"help_text": "Your JamKazam subscription plan is currently set to the plan displayed below. To change your plan, click the subscription plan box below, select a new plan from the list, and then click the Save Plan button.",
|
||||
"subscription_plan": "Subscription Plan",
|
||||
"validations": {
|
||||
"subscription_plan": {
|
||||
"required": "Subscription plan is required"
|
||||
}
|
||||
},
|
||||
"submit": "Save Plan",
|
||||
"notice": {
|
||||
"part1": "To compare the features available for different subscription plans ",
|
||||
"click_here": "click here",
|
||||
"part2": " to view a help article on our available plans."
|
||||
|
||||
}
|
||||
},
|
||||
"play_time": {
|
||||
"title": "Tiempo de juego",
|
||||
"description": ""
|
||||
},
|
||||
"alerts": {
|
||||
"title": "Subscription Plan Update",
|
||||
"changed_to_free_plan": "You have chosen to go back down to the FREE PLAN. Your subscription will be canceled, and you will keep your plan until the end of the current billing cycle.",
|
||||
"failed_to_change_plan": "Failed to update subscription plan. Please try again later. Please contact support@jamkazam.com if you continue to have problems.",
|
||||
"changed_plan_successfully": "You have successfully updated your subscription plan."
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue