Skip to content

Commit

Permalink
Merge pull request #131 from effective-altruism-australia/amplify-imp…
Browse files Browse the repository at this point in the history
…act-option

Amplify impact option
  • Loading branch information
nathansherburn authored Jan 6, 2025
2 parents c478aec + 7bd5dc0 commit ac5fa61
Show file tree
Hide file tree
Showing 67 changed files with 3,158 additions and 1,122 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# For local development and testing only.

FROM ubuntu:16.04
FROM --platform=linux/amd64 ubuntu:16.04

# Install sudo
RUN apt-get update && apt-get install -y sudo
Expand Down
6 changes: 6 additions & 0 deletions donation/views/pledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ def process_session_completed(data):
@app.task()
def process_payment_intent_succeeded(data, org):
print(org)

# Ignore duplicate events (Stripe sometimes sends the same event multiple times).
# See here for more: https://docs.stripe.com/webhooks#handle-duplicate-events
if StripeTransaction.objects.filter(payment_intent_id=data['id']).exists():
return

stripe.api_key = settings.STRIPE_API_KEY_DICT.get(org)

if org == "eaa":
Expand Down
9 changes: 4 additions & 5 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ This form is designed to replace our react-based donation form. The goals of thi
**Easy to customise** - just clone this repo and change the HTML/CSS/JS as needed.
**Easy to maintain** - only a few hundred lines of simple code that beginners can grok.

## Terminology

## Allocation terminology
| Term | Description |
|--------|---------------|
| Default allocation | This option allocates the donation to the most effective charities (according to us), based on evidence and need. This option is selected by default in the standard form. |
| Custom allocation | This option allows donors to allocate their donation to our various partner charities. This option can be selected in the standard form. |
| Specific charity | A specific charity is an EAA partner charity selected by visiting our `/donate` url with `?charity=charity_name` appended to the end. Specific charities are not relevant to the standard form. |
| Most effective (default) | This option allocates the donation to the most effective charities (according to us), based on evidence and need. This option is selected by default in the standard form. |
| Specific charity (or charities) | This option allows donors to allocate their donation to our various partner charities. This option can be selected in the standard form. |
| Direct link charity | A direct link charity is an EAA partner charity selected by visiting our `/donate` url with `?charity=charity_name` appended to the end. Direct link charities are not relevant to the standard form. |

## Compatibility
We try to only use features that are "Widely available" according to [Baseline](https://web.dev/baseline) to ensure compatibility with all modern browsers.
Expand Down
11 changes: 6 additions & 5 deletions frontend/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ const donationFormHtml = `
${fs.readFileSync("./src/styles/custom-inputs.css", "utf8")}
</style>
<form onsubmit="return handleFormSubmit();">
<form onsubmit="return formController.handleFormSubmit();">
${fs.readFileSync("./src/donation-frequency-section.html", "utf8")}
${fs.readFileSync("./src/allocation-section.html", "utf8")}
${fs.readFileSync("./src/specific-charity-section.html", "utf8")}
${fs.readFileSync("./src/direct-link-charity-section.html", "utf8")}
${fs.readFileSync("./src/amount-section.html", "utf8")}
${fs.readFileSync("./src/custom-allocation-section.html", "utf8")}
${fs.readFileSync("./src/specific-allocation-section.html", "utf8")}
${fs.readFileSync("./src/amplify-impact-section.html", "utf8")}
${fs.readFileSync("./src/total-amount-section.html", "utf8")}
${fs.readFileSync("./src/personal-details-section.html", "utf8")}
${fs.readFileSync("./src/communications-section.html", "utf8")}
${fs.readFileSync("./src/payment-method-section.html", "utf8")}
Expand All @@ -61,8 +63,7 @@ const donationFormHtml = `
const STRIPE_API_KEY_EAA = "${process.env.STRIPE_API_KEY_EAA}";
const ORIGIN = "${process.env.ORIGIN}";
${fs.readFileSync("./src/scripts/utilities.js", "utf8")}
${fs.readFileSync("./src/scripts/countries.js", "utf8")}
${fs.readFileSync("./src/scripts/main.js", "utf8")}
${fs.readFileSync("./src/scripts/FormController.js", "utf8")}
</script>
<!-- Paste this into WordPress: END -->
Expand Down
44 changes: 33 additions & 11 deletions frontend/src/allocation-section.html
Original file line number Diff line number Diff line change
@@ -1,33 +1,55 @@
<section id="allocation-section" style="display: none">
<style>
#allocation-section {
display: none;
}
</style>

<section id="allocation-section">
<h2 class="text-lg mt-8">I would like my gift to go to</h2>
<div class="radio-group flex gap-2 mb-4">
<input
type="radio"
id="default-allocation"
name="allocation-type"
id="allocation-section--default-allocation"
name="allocation-section--allocation-type"
value="default"
checked
onclick="hide('#custom-allocation-section'); showBlock('#amount-section');"
onclick="AllocationSection.handleDefaultAllocationChange();"
/>
<label for="default-allocation" class="flex items-center justify-center rounded text-blue">
<label for="allocation-section--default-allocation" class="flex items-center justify-center rounded text-blue">
The most effective charities^
</label>

<input
type="radio"
id="custom-allocation"
name="allocation-type"
value="custom"
onclick="hide('#amount-section'); showBlock('#custom-allocation-section');"
id="allocation-section--specific-allocation"
name="allocation-section--allocation-type"
value="specific"
onclick="AllocationSection.handleSpecificAllocationChange();"
/>
<label for="custom-allocation" class="flex items-center justify-center rounded text-blue">
<label for="allocation-section--specific-allocation" class="flex items-center justify-center rounded text-blue">
These specific charities
</label>
</div>
<p style="font-size: small;">
<p class="text-sm">
^According to EAA. We select the most effective charities each quarter
based on evidence and need. You can read more about how we evaluate
charities
<a href="https://effectivealtruism.org.au/evaluating-charities/">here</a>.
</p>
</section>

<script>
class AllocationSection {
constructor() {
$("#allocation-section").style.display = "block";
}

static handleSpecificAllocationChange() {
formController.setAllocationType("specific");
}

static handleDefaultAllocationChange() {
formController.setAllocationType("default");
}
}
</script>
140 changes: 103 additions & 37 deletions frontend/src/amount-section.html
Original file line number Diff line number Diff line change
@@ -1,78 +1,144 @@
<style>
#custom-amount-input {
display: flex;
flex-grow: 1;
border: none;
background-color: transparent;
outline: none;
padding: 0.5rem 0.5rem 0.5rem 0.25rem;
}
#input-wrapper {
display: flex;
flex-grow: 1;
align-items: center;
padding-left: 0.5rem;
width: 100%;
background-color: white;
#amount-section {
display: none;

#amount-section--custom-amount-input {
display: flex;
flex-grow: 1;
border: none;
background-color: transparent;
outline: none;
padding: 1rem 0.5rem;
}

#amount-section--custom-amount-input-wrapper {
display: flex;
flex-grow: 1;
align-items: center;
padding-left: 0.5rem;
width: 100%;
background-color: white;
border: 2px solid var(--eaa-blue-600);
}

.larger-button {
padding: 1rem 0;
border: 2px solid var(--eaa-blue-600);
font-size: 1.2rem;
}
}
</style>

<section id="amount-section" style="display: none">
<section id="amount-section">
<h2 class="text-lg mt-8">I would like to gift</h2>
<div class="radio-group flex gap-2">
<input
type="radio"
id="donate-25"
id="amount-section--donate-25"
name="donation-amount"
value="25"
onchange="$('#custom-amount').classList.remove('validate'); $('#custom-amount-input').value = '';"
onchange="AmountSection.handleSuggestedAmountChange(event)"
/>
<label for="donate-25" class="rounded text-blue">$25</label>
<label for="amount-section--donate-25" class="rounded text-blue larger-button">$25</label>
<input
type="radio"
id="donate-50"
id="amount-section--donate-50"
name="donation-amount"
value="50"
onchange="$('#custom-amount').classList.remove('validate'); $('#custom-amount-input').value = '';"
onchange="AmountSection.handleSuggestedAmountChange(event)"
/>
<label for="donate-50" class="rounded text-blue">$50</label>
<label for="amount-section--donate-50" class="rounded text-blue larger-button">$50</label>
<input
type="radio"
id="donate-100"
id="amount-section--donate-100"
name="donation-amount"
value="100"
onchange="$('#custom-amount').classList.remove('validate'); $('#custom-amount-input').value = '';"
onchange="AmountSection.handleSuggestedAmountChange(event)"
/>
<label for="donate-100" class="rounded text-blue">$100</label>
<label for="amount-section--donate-100" class="rounded text-blue larger-button"
>$100</label
>
<input
type="radio"
id="donate-250"
id="amount-section--donate-250"
name="donation-amount"
value="250"
onchange="$('#custom-amount').classList.remove('validate'); $('#custom-amount-input').value = '';"
onchange="AmountSection.handleSuggestedAmountChange(event)"
/>
<label for="donate-250" class="rounded text-blue">$250</label>
<label for="amount-section--donate-250" class="rounded text-blue larger-button"
>$250</label
>
</div>
<div id="custom-amount" class="flex flex-col validate mb-2">
<div id="amount-section--custom-amount" class="flex flex-col validate mb-2">
<label class="inline-block mb-2 mt-4" for="custom-amount-input"
>Or a custom amount:</label
>
<span id="input-wrapper" class="border rounded">
<span
id="amount-section--custom-amount-input-wrapper"
class="border rounded focus-outline"
>
$
<input
type="number"
inputmode="numeric"
min="2"
min="0"
max="999999.99"
step="1"
id="custom-amount-input"
step="0.01"
id="amount-section--custom-amount-input"
name="custom-amount-input"
class="inline-block text-md"
onblur="this.value === '' ? $('#custom-amount').classList.remove('validate') : '';"
onfocus="$('#custom-amount').classList.add('validate'); $('#input-wrapper').classList.add('selected'); $('#donate-25').checked = false; $('#donate-50').checked = false; $('#donate-100').checked = false; $('#donate-250').checked = false;"
tabindex="-1"
class="inline-block text-md larger-input"
onblur="AmountSection.handleCustomAmountBlur()"
onfocus="AmountSection.handleCustomAmountFocus(event)"
oninput="AmountSection.handleCustomAmountChange()"
placeholder="Enter your custom amount here"
/>
</span>
</div>
</section>

<script>
class AmountSection {
constructor() {
$("#amount-section").style.display = "block";
}

static handleCustomAmountFocus(e) {
formController.setBasicDonationAmount(e.target.value);
$("#amount-section--custom-amount").classList.add("validate");
$("#amount-section--donate-25").checked = false;
$("#amount-section--donate-50").checked = false;
$("#amount-section--donate-100").checked = false;
$("#amount-section--donate-250").checked = false;
}

static handleCustomAmountBlur() {
if ($("#amount-section--custom-amount-input").value === "") {
$("#amount-section--custom-amount").classList.remove("validate");
}
}

static handleSuggestedAmountChange(e) {
const selectedAmount = e.target.value;
formController.setBasicDonationAmount(selectedAmount);
$("#amount-section--custom-amount").classList.remove("validate");
$("#amount-section--custom-amount-input").value = "";
}

static handleCustomAmountChange() {
const customAmount = $("#amount-section--custom-amount-input").value;
formController.setBasicDonationAmount(customAmount);
$("#amount-section--donate-25").checked = false;
$("#amount-section--donate-50").checked = false;
$("#amount-section--donate-100").checked = false;
$("#amount-section--donate-250").checked = false;
}

static show() {
$("#amount-section").style.display = "block";
}

static hide() {
$("#amount-section").style.display = "none";
}
}
</script>
Loading

0 comments on commit ac5fa61

Please sign in to comment.