289 lines
9.0 KiB
HTML
289 lines
9.0 KiB
HTML
{%- extends "templates/saas/billing_layout.html" -%} {%- from
|
|
"templates/saas/macros.html" import subs_wrapper, plans_wrapper, success_card,
|
|
error_card, load_stripe, load_subs, checkout_wrapper, stripe_wrapper,
|
|
address_wrapper, email_verify_wrapper -%} {% block content %}
|
|
<div class="flex justify-content-center mx-auto my-auto h-100 w-100">
|
|
{{ subs_wrapper() }} {{ plans_wrapper() }} {{ address_wrapper() }} {{
|
|
checkout_wrapper() }} {{ stripe_wrapper() }} {{ success_card() }} {{
|
|
success_card() }} {{ load_stripe() }} {{ load_subs() }} {{ email_verify_wrapper() }}
|
|
</div>
|
|
{%- endblock -%} {%- block script -%}
|
|
<script src="https://js.stripe.com/v3/"></script>
|
|
<script>
|
|
const url_args = jingrow.utils.get_query_params();
|
|
let secret_key = url_args.secret_key;
|
|
let address = null;
|
|
let elements = null;
|
|
let stripe = null;
|
|
let response = {};
|
|
let gstApplicable = false
|
|
|
|
if (secret_key.length >= 0 && secret_key != null) {
|
|
setup();
|
|
}
|
|
|
|
function setup() {
|
|
return call('jcloude.api.developer.marketplace.get_subscriptions', {
|
|
secret_key: secret_key,
|
|
}).then((r) => {
|
|
let data = r.message;
|
|
address = data.address;
|
|
let subscriptions = data.subscriptions;
|
|
response.currency = data.currency;
|
|
response.team = data.team
|
|
|
|
if (subscriptions.length >= 0) {
|
|
$('#loading').toggleClass('hidden');
|
|
$('#subs-wrapper').toggleClass('hidden');
|
|
|
|
for (let i in subscriptions) {
|
|
$('#subs-wrapper').append(`
|
|
<div class="flex flex-col items-center m-2 p-4 w-2/7 rounded cursor-pointer transition-all" onclick='showPlans(${JSON.stringify(
|
|
subscriptions[i]
|
|
)})'>
|
|
<img src="${
|
|
subscriptions[i].image
|
|
}" alt="Logo" class="rounded mr-2 h-[64px] hover:scale-105 transition-all" />
|
|
<span class="text-sm mt-3 font-semibold">${subscriptions[i].title}</span>
|
|
</div>
|
|
`);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function showPlans(sub) {
|
|
$('#subs-wrapper').toggleClass('hidden');
|
|
$('#plans-wrapper').toggleClass('hidden');
|
|
|
|
response.sub_name = sub.name;
|
|
response.app = sub.app;
|
|
response.site = sub.site;
|
|
|
|
let plans = sub.available_plans;
|
|
let style =
|
|
'flex flex-col flex-1 justify-content-between m-2 border rounded col-md-auto shadow-sm';
|
|
|
|
// FC Plans Redirect
|
|
$('#plans-wrapper').append(`
|
|
<div class="flex flex-col flex-1 justify-content-between m-2 border rounded col-md-auto shadow-sm" style="width: 220px;" >
|
|
<div>
|
|
<p class="mt-4 font-semibold text-sm">Jingrow Cloud Plans</p>
|
|
<span class="my-4 font-bold text-xl">${response.currency === 'INR' ? '₹ 750' : '$ 10'} Onwards</span>
|
|
<div class="flex flex-col">
|
|
|
|
<div class="flex my-1">
|
|
<div class="mr-2 grid h-4 w-4 shrink-0 place-items-center rounded-full border border-green-500 bg-green-50">
|
|
<svg width="10" height="8" viewBox="0 0 10 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M1.26562 3.86686L3.93229 6.53353L9.26562 1.2002" stroke="#38A160" stroke-miterlimit="10"
|
|
stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</div>
|
|
<p>Site Hosting Support</p>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<button id="email-verify-btn" class='rounded my-4 w-full bg-gray-100 btn' onclick='sendLoginLink()'>Send Login Link</button>
|
|
</div>
|
|
`)
|
|
for (let i in plans) {
|
|
let features = '';
|
|
plans[i].features.map((f) => {
|
|
features += `<div class="flex my-1">
|
|
<div class="mr-2 grid h-4 w-4 shrink-0 place-items-center rounded-full border border-green-500 bg-green-50">
|
|
<svg width="10" height="8" viewBox="0 0 10 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M1.26562 3.86686L3.93229 6.53353L9.26562 1.2002" stroke="#38A160" stroke-miterlimit="10"
|
|
stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</div>
|
|
<p>${f}</p>
|
|
</div>`;
|
|
});
|
|
|
|
$('#plans-wrapper').append(`
|
|
<div class="${style} ${
|
|
sub.marketplace_app_plan === plans[i].name ? 'border-primary' : ''
|
|
}" style="width: 220px;" >
|
|
<div>
|
|
<p class="mt-4 font-semibold text-sm">${plans[i].plan}</p>
|
|
<span class="my-4 font-bold text-xl">${response.currency === 'INR' ? '₹' : '$'}${
|
|
plans[i][`price_${response.currency.toLowerCase()}`]
|
|
}<span class="text-xs text-gray-500"> / mo</span></span>
|
|
<div class="flex flex-col">
|
|
${features}
|
|
</div>
|
|
</div>
|
|
<button class='btn btn-primary rounded my-4 w-full bg-gray-100 btn ${
|
|
sub.marketplace_app_plan === plans[i].name
|
|
? 'btn-primary disabled'
|
|
: 'active-btn'
|
|
}' onclick='selectPlan(${JSON.stringify(plans[i])}, "${sub.name}")'>
|
|
${sub.marketplace_app_plan === plans[i].name ? 'Current Plan' : 'Buy Now'}
|
|
</button>
|
|
</div>
|
|
`);
|
|
}
|
|
}
|
|
|
|
function setTotal(billing) {
|
|
let total = 0;
|
|
const plan_price =
|
|
response.new_plan[`price_${response.currency.toLowerCase()}`];
|
|
total = billing === 'annual' ? plan_price * 12 : plan_price;
|
|
$('.new-plan').text(response.new_plan.plan);
|
|
$('.new-plan-price').text(
|
|
`${response.currency === 'INR' ? '₹' : '$'} ${plan_price}`
|
|
);
|
|
|
|
if (response.new_plan.discounted && billing === 'annual') {
|
|
let discount_percent = response.new_plan.discount_percent;
|
|
$('.discount').text(`${discount_percent}%`);
|
|
total -= total * (discount_percent / 100);
|
|
} else {
|
|
$('.discount').text('-');
|
|
}
|
|
if (response.currency === 'INR' && response.new_plan.gst === 1) {
|
|
$('.gst').text('18%');
|
|
total += total * 0.18;
|
|
} else {
|
|
$('gst').text('-');
|
|
}
|
|
|
|
response.total = total;
|
|
response.billing = billing;
|
|
$('.total').text(`${response.currency === 'INR' ? '₹' : '$'} ${total}`);
|
|
}
|
|
|
|
function setupStripe() {
|
|
$('#checkout-wrapper').toggleClass('hidden');
|
|
|
|
$('#loading-stripe').toggleClass('hidden');
|
|
call('jcloude.api.developer.marketplace.saas_payment', {
|
|
secret_key: secret_key,
|
|
data: response,
|
|
}).then((r) => {
|
|
$('#loading-stripe').toggleClass('hidden');
|
|
if (r.message) {
|
|
r = r.message;
|
|
$('#stripe-wrapper').toggleClass('hidden');
|
|
stripe = Stripe(r.publishable_key);
|
|
const options = {
|
|
clientSecret: r.client_secret,
|
|
appearance: {
|
|
theme: 'flat',
|
|
},
|
|
};
|
|
elements = stripe.elements(options);
|
|
const paymentElement = elements.create('payment');
|
|
paymentElement.mount('#card');
|
|
|
|
$('#card').toggleClass('hidden');
|
|
}
|
|
});
|
|
}
|
|
|
|
async function handlePayment(e) {
|
|
try {
|
|
$('#pay-btn').attr('disabled', 'disabled');
|
|
$('#pay-btn-spinner').toggleClass('hidden');
|
|
$('#pay-btn-text').text('Processing...');
|
|
|
|
const payload = await stripe.confirmPayment({
|
|
elements,
|
|
redirect: 'if_required',
|
|
});
|
|
|
|
if (payload.error && payload.error === 'card_error') {
|
|
$('#stripe-wrapper').toggleClass('hidden');
|
|
$('#success-wrapper').toggleClass('hidden');
|
|
} else {
|
|
if (payload.paymentIntent.status === 'succeeded') {
|
|
$('#stripe-wrapper').toggleClass('hidden');
|
|
$('#success-wrapper').toggleClass('hidden');
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.log(err);
|
|
$('#pay-btn').removeAttr('disabled');
|
|
$('#pay-btn-spinner').toggleClass('hidden');
|
|
$('#pay-btn-text').text('Pay Now');
|
|
}
|
|
}
|
|
|
|
function selectPlan(new_plan, sub) {
|
|
response.new_plan = new_plan;
|
|
response.sub = sub;
|
|
$('#plans-wrapper').toggleClass('hidden');
|
|
if (address) {
|
|
$('#checkout-wrapper').toggleClass('hidden');
|
|
setTotal('monthly');
|
|
} else {
|
|
$('#address-card-wrapper').toggleClass('hidden');
|
|
}
|
|
}
|
|
|
|
function toggleGSTField(show) {
|
|
gstApplicable = show
|
|
$('#gstinhide').toggleClass('hidden')
|
|
$('#gstinshow').toggleClass('hidden')
|
|
|
|
$('#gstin').toggleClass('hidden')
|
|
}
|
|
|
|
function updateBillingInfo() {
|
|
let billing_info = {
|
|
billing_name: $('input[name="billing-name"]').val(),
|
|
address: $('input[name="address"]').val(),
|
|
country: $('select[name="country"]').val(),
|
|
city: $('input[name="city"]').val(),
|
|
state: $('input[name="state"]').val(),
|
|
postal_code: $('input[name="postal-code"]').val(),
|
|
gstin: gstApplicable ? $('input[name="gstin"]').val() : 'Not Applicable',
|
|
};
|
|
|
|
call('jcloude.api.developer.marketplace.update_billing_info', {
|
|
secret_key: secret_key,
|
|
data: billing_info,
|
|
}).then((r) => {
|
|
if (r.message == 'success') {
|
|
$('#checkout-wrapper').toggleClass('hidden');
|
|
$('#address-card-wrapper').toggleClass('hidden');
|
|
setTotal('monthly');
|
|
}
|
|
});
|
|
}
|
|
|
|
function sendLoginLink() {
|
|
|
|
$('#email-verify-btn').prop('disabled', true)
|
|
$("#email-verify-btn").html('<span class="mr-2">Sending</span><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>');
|
|
|
|
call('jcloude.api.developer.marketplace.send_login_link', {
|
|
secret_key: secret_key,
|
|
}).then((r) => {
|
|
if (r.message && r.message === "success") {
|
|
$('#plans-wrapper').toggleClass('hidden')
|
|
$('#email-verify-wrapper').toggleClass('hidden')
|
|
$('#verification-email').text(response.team)
|
|
}
|
|
})
|
|
}
|
|
|
|
function call(method, args) {
|
|
return jingrow
|
|
.call({
|
|
method: method,
|
|
args: args,
|
|
type: 'POST',
|
|
})
|
|
.then((r) => {
|
|
if (r.exc) {
|
|
console.error('An error occurred', r.exc);
|
|
return;
|
|
}
|
|
return r;
|
|
});
|
|
}
|
|
</script>
|
|
{% endblock %} |