// I sincerely apologise for the garbage you're about to see // This file is public domain, I guess. If you use this I would appreciate // it if you linked back to my blog, but I ain't a cop. import React, { Component } from 'react'; import ReactDOM from 'react-dom'; const vatRates = { "Austria": 0.20, "Belgium": 0.21, "Bulgaria": 0.20, "Croatia": 0.25, "Cyprus": 0.19, "Czech Republic": 0.21, "Denmark": 0.25, "Estonia": 0.20, "Finland": 0.24, "France": 0.20, "Germany": 0.19, "Greece": 0.24, "Hungary": 0.27, "Ireland": 0.23, "Italy": 0.22, "Latvia": 0.21, "Lithuania": 0.21, "Luxembourg": 0.17, "Malta": 0.18, "Netherlands": 0.21, "Poland": 0.23, "Portugal": 0.23, "Romania": 0.19, "Slovakia": 0.20, "Slovenia": 0.22, "Spain": 0.21, "Sweden": 0.25, }; class Calculator extends Component { constructor() { super(); this.state = { country: "Germany", amount: "5.00", paypal: false, vat: false, patreonCreators: [ { id: 0, username: "SirCmpwn", amount: 5, displayAmount: "5.00", founding: true, plan: "pro", upfront: false, } ] }; this.renderPatreon = this.renderPatreon.bind(this); } patreonFee(creator) { let text, rate, fixed; if (creator.founding) { return { text: "5%", fee: creator.amount * 0.05, }; } else { switch (creator.plan) { case "lite": return { text: "5%", fee: creator.amount * 0.05, }; case "pro": if (creator.founding) { return { text: "5%", fee: creator.amount * 0.05, }; } return { text: "8%", fee: creator.amount * 0.08, }; case "premium": if (creator.founding) { return { text: "9%", fee: creator.amount * 0.09, }; } return { text: "12%", fee: creator.amount * 0.12, }; } } } transactionFee(creator, paypal) { let text, rate, fixed; if (creator === null) { return { text: paypal ? "3.9% + 30¢" : "2.9% + 30¢", }; } if (creator.founding && creator.upfront) { return { text: paypal ? "3.9% + 30¢" : "2.9% + 30¢", fee: creator.amount * (paypal ? 0.039 : 0.029) + 0.30, }; } else { if (creator.amount <= 3) { return { text: paypal ? "5% + 10¢" : "5% + 10¢", fee: creator.amount * (paypal ? 0.06 : 0.05) + 0.10, }; } else { return { text: paypal ? "3.9% + 30¢" : "2.9% + 30¢", fee: creator.amount * 0.029 + 0.30, }; } } } renderPatreon() { const creators = this.state.patreonCreators.slice() .sort((a, b) => a.id - b.id); const { country, paypal, vat } = this.state; const total = creators.reduce((a, c) => a + c.amount, 0); const batch_total = creators .filter(c => c.founding && !c.upfront) .reduce((a, c) => a + c.amount, 0); const batch_tx_fee = batch_total ? batch_total * (this.state.paypal ? 0.039 : 0.029) + 0.30 : 0; const tx_fees = creators.filter(c => !c.founding || c.upfront) .reduce((a, c) => a + this.transactionFee(c, paypal).fee, 0) + batch_tx_fee; const patreon_fees = creators.reduce((a, c) => a + this.patreonFee(c).fee, 0); const total_fees = tx_fees + patreon_fees; const total_after_fees = total - total_fees; return (
{creators.map(creator =>
this.setState({ patreonCreators: [ { ...creator, username: e.target.value }, ...creators.filter(c => c.id != creator.id) ] })} value={creator.username} />
$ this.setState({ patreonCreators: [ { ...creator, amount: parseFloat(e.target.value), displayAmount: e.target.value, }, ...creators.filter(c => c.id != creator.id) ] })} value={creator.displayAmount} /> per month
{creator.plan === "premium" ?

Note: Large creators with a premium plan may receive a special rate.

: null}
)}
{creators.length > 1 && }

You only pay one transaction fee between all of your founding creators, except for creators which use the "charge up front" option. You get charged a separate transaction fee for each non-founding creator you support, based on your pledge amount.

{vat ?

Unlike other fees, adding VAT increases the amount you actually pay, rather than subtracting more fees from your base pledge.

: null} {vat ? : null} {batch_tx_fee !== 0 ? : null} {creators.filter(c => !c.founding || c.upfront).map(c => { return ; })}
You pay ${(vat ? total * vatRates[country] + total : total).toFixed(2)}
VAT {(vatRates[country] * 100).toFixed(2)}% (${(total * vatRates[country]).toFixed(2)})
Transaction fee (batch) {this.transactionFee(null, paypal).text}2 (${batch_tx_fee.toFixed(2)})
Transaction fee ({c.username}) {this.transactionFee(c, paypal).text}2 (${this.transactionFee(c, paypal).fee.toFixed(2)})
Payment processing fees = ${tx_fees.toFixed(2)}

Patreon also charges its own fees, depending on the creator's plan and founder status.

{creators.map(c => { return ; })}
You pay ${total.toFixed(2)}
Patreon fee ({c.username}) {this.patreonFee(c).text} (${this.patreonFee(c).fee.toFixed(2)})
Patreon fees = ${patreon_fees.toFixed(2)}

Your total minus the transaction fees & Patreon fees is distributed to your creators like so:

{creators.map(c => { const tx_fee = this.transactionFee(c, paypal); if (c.founding && !c.upfront) { tx_fee.fee = (c.amount / batch_total) * batch_tx_fee; } const patreon_fee = this.patreonFee(c); const clamp = (value, min, max) => Math.min(Math.max(min, value), max); const creator_total = c.amount - tx_fee.fee - patreon_fee.fee; return [ , , , , , ]; })}
{c.username}
You pay ${c.amount.toFixed(2)}
Transaction fees {c.founding && !c.upfront ? '(see above)' : tx_fees.text} (${tx_fee.fee.toFixed(2)})
Patreon fees {patreon_fee.text} (${patreon_fee.fee.toFixed(2)})
Creator earns ${creator_total.toFixed(2)} per month
{(creator_total / c.amount * 100).toFixed(0)}% of your donation

After all is said and done, of the ${total.toFixed(2)} you spend on Patreon, ${total_after_fees.toFixed(2)}, or {(total_after_fees / total * 100).toFixed(0)}% makes it to your creators.

); } render() { return (
Fee Calculator (based on 2019-05-07 fees)
{this.renderPatreon()}
); } } ReactDOM.render(, document.getElementById("react-root"));