]> git.ipfire.org Git - ipfire.org.git/blame - src/templates/donate/donate.html
donate: Implement a basic VAT number check
[ipfire.org.git] / src / templates / donate / donate.html
CommitLineData
c7bcb9ca 1{% extends "../base.html" %}
95b30f84 2
9b5ac075 3{% block title %}{{ _("Donate") }}{% end block %}
95b30f84 4
60b0917c 5{% block container %}
95b30f84
MT
6 {% set amounts = (10, 25, 50, 75, 100, 250) %}
7
45cfec9a
RH
8 <section class="hero is-primary">
9 <div class="hero-body">
10 <div class="container">
ed83981e 11 <nav class="breadcrumb" aria-label="breadcrumbs">
45cfec9a
RH
12 <ul>
13 <li>
14 <a href="/">Home</a>
15 </li>
16 <li class="is-active">
17 <a href="#" aria-current="page">Donate</a>
18 </li>
19 </ul>
20 </nav>
ed83981e 21 <h1 class="title">
45cfec9a
RH
22 Donate
23 </h1>
24 <p class="subtitle">{{ _("Please support our project with your donation today") }}</p>
0ccdfa9d
MT
25 </div>
26 </div>
27 </section>
95b30f84 28
45cfec9a 29 <section class="section">
6f151c32 30 <div class="container">
45cfec9a
RH
31 <div class="columns">
32 <div class="column is-8">
3d24a78c 33 <form id="donation-form" action="" method="POST">
6f151c32
MT
34 {% raw xsrf_form_html() %}
35
45cfec9a
RH
36 <h5 class="title is-5">I am an ...</h5>
37
38 <input type="hidden" name="type" value="individual">
6f151c32 39
45cfec9a
RH
40 <div class="block">
41 <div class="control">
42 <label class="radio">
43 <input class="custom-control-input" type="radio"
44 name="type-selector" id="type-individual" value="individual" checked>
d1f119e3 45
45cfec9a
RH
46 {{ _("Individual") }}
47 </label>
48 <label class="custom-control-label" for="type-individual"></label>
49 <label class="radio">
50 <input class="custom-control-input" type="radio"
51 name="type-selector" id="type-organization" value="organization">
52
53 {{ _("Organization") }}
54 </label>
55 <label class="custom-control-label" for="type-organization"></label>
56 </div>
57 </div>
58
59 <h5 class="title is-5">Frequency</h5>
60
61 <input type="hidden" name="frequency" value="{{ frequency }}">
62
63 <div class="block">
64 <div class="control">
65 <label class="radio">
d7a9cbd3 66 <input class="form-check-input" type="radio" name="frequency-selector" id="frequency-one-time"
6f151c32 67 value="one-time" {% if frequency == "one-time" %}checked{% end %}>
95b30f84 68
45cfec9a
RH
69 {{ _("One Time") }}
70 </label>
71 <label class="form-check-label" for="frequency-one-time"></label>
72
73 <label class="radio">
d7a9cbd3 74 <input class="form-check-input" type="radio" name="frequency-selector" id="frequency-monthly"
6f151c32 75 value="monthly" {% if frequency == "monthly" %}checked{% end %}>
45cfec9a
RH
76
77 {{ _("Monthly") }}
78 </label>
79 <label class="form-check-label" for="frequency-monthly"></label>
f89c578d 80 </div>
6f151c32 81 </div>
95b30f84 82
45cfec9a
RH
83 <div class="block">
84 <h5 class="title is-5">{{ _("Choose an amount") }}</h5>
85 </div>
a41e6d77 86
45cfec9a
RH
87 <input type="hidden" name="currency" value="{{ currency }}">
88
89 <div class="block">
90 <div class="buttons" data-toggle="buttons">
91 <p class="control">
92 {% for a in amounts %}
93 <label class="button is-outlined is-primary">
94 <input type="radio" name="amount-selector" value="{{ a }}" {% if amount == a %}checked{% end %}
95 autocomplete="off" class="is-hidden"> <span class="EUR">€</span><span class="USD">$</span>{{ a }}
96 </label>
97 {% end %}
98 </p>
99 </div>
100 </div>
a41e6d77 101
45cfec9a
RH
102 <div class="block">
103 <h6 class="title is-6">Or Enter your own</h6>
104
105 <div class="columns">
106 <div class="column is-3">
107 <div class="field">
108 <p class="control has-icons-left">
109 <input type="number" class="input" name="amount" min="5" step="0.01"
110 {% if amount %}value="{{ "%.2f" % amount }}"{% end %}>
111 <span class="input-group-text EUR icon is-small is-left">
112 <i class="fas fa-euro-sign"></i>
113 </span>
114 <span class="input-group-text USD icon is-small is-left">
115 <i class="fas fa-dollar-sign"></i>
116 </span>
117 </p>
118 </div>
119 </div>
6f151c32 120 </div>
a41e6d77 121
45cfec9a
RH
122 <p class="small text-end">
123 <a class="toggleCurrency EUR" href="#">{{ _("Prefer donating in US Dollar?") }}</a>
124 <a class="toggleCurrency USD" href="#">{{ _("Prefer donating in Euro?") }}</a>
6f151c32 125 </p>
45cfec9a 126 </div>
a6100896 127
45cfec9a 128 <div class="block">
bd09b86a
RH
129 <div class="control">
130 <div class="organization organization-required">
131 <input type="text" class="input" name="organization"
132 placeholder="{{ _("Organization") }}">
133 </div>
45cfec9a
RH
134 </div>
135 </div>
136 <div class="block">
bd09b86a
RH
137 <div class="control">
138 <div class="organization">
139 <input type="text" class="input" name="vat_number"
140 placeholder="{{ _("VAT Number") }}">
141 </div>
45cfec9a
RH
142 </div>
143 </div>
144 <div class="block">
145 <div class="organization">
146 <p class="is-size-6">
147 If you are an organization in Europe and you are VAT-registered,
148 please provide your VAT number here.
149 It will make your donation VAT free (if applicable) and the project
150 will benefit from more of your help
151 Please see the FAQ below for more details about VAT.
152 </p>
153 </div>
154 </div>
6f151c32 155
45cfec9a
RH
156 <div class="columns">
157 <div class="column is-2">
bd09b86a 158 <div class="control">
45cfec9a
RH
159 <input class="form-check-input" type="radio" name="title" id="mr" value="Mr." checked>
160 <label class="form-check-label" for="mr">{{ _("Mr.") }}</label>
f89c578d 161 </div>
6f151c32 162 </div>
45cfec9a 163 <div class="column is-2">
bd09b86a 164 <div class="control">
45cfec9a
RH
165 <input class="form-check-input" type="radio" name="title" id="mrs" value="Mrs.">
166 <label class="form-check-label" for="mrs">{{ _("Mrs.") }}</label>
167 </div>
168 </div>
169 </div>
6f151c32 170
45cfec9a
RH
171 <div class="columns">
172 <div class="column">
bd09b86a
RH
173 <div class="control">
174 <input type="text" class="input" name="first_name"
175 placeholder="{{ _("First Name" )}}" required
0ad196e7 176 {% if current_user %}value="{{ current_user.first_name }}"{% end %}>
bd09b86a 177 </div>
45cfec9a 178 </div>
a41e6d77 179
45cfec9a 180 <div class="column">
bd09b86a
RH
181 <div class="control">
182 <input type="text" class="input" name="last_name"
183 placeholder="{{ _("Last Name" )}}" required
0ad196e7 184 {% if current_user %}value="{{ current_user.last_name }}"{% end %}>
bd09b86a 185 </div>
45cfec9a
RH
186 </div>
187 </div>
f89c578d 188
45cfec9a 189 <div class="block">
bd09b86a 190 <div class="control">
45cfec9a 191 <input type="email" class="input" name="email"
1898a8bb
MT
192 placeholder="{{ _("Email Address") }}" required
193 {% if current_user %}value="{{ current_user.email }}"{% end %}>
bd09b86a 194 </div>
45cfec9a 195 </div>
a41e6d77 196
df94eed7 197 {% set lines = current_user.street.splitlines() if current_user and current_user.street else [] %}
1898a8bb 198
45cfec9a 199 <div class="block">
bd09b86a
RH
200 <div class="control">
201 <input type="text" class="input" name="street1"
0ad196e7
MT
202 placeholder="{{ _("Address Line 1") }}" required
203 {% if lines %}value="{{ lines[0] }}"{% end %}>
bd09b86a 204 </div>
45cfec9a 205 </div>
f89c578d 206
45cfec9a 207 <div class="block">
bd09b86a
RH
208 <div class="control">
209 <input type="text" class="input" name="street2"
0ad196e7
MT
210 placeholder="{{ _("Address Line 2") }}"
211 {% if lines and len(lines) > 1 %}value="{{ lines[1] }}"{% end %}>
bd09b86a 212 </div>
45cfec9a 213 </div>
f89c578d 214
45cfec9a
RH
215 <div class="columns">
216 <div class="column">
bd09b86a
RH
217 <div class="control">
218 <input type="text" class="input" name="city"
0ad196e7
MT
219 placeholder="{{ _("City") }}" required
220 {% if current_user %}value="{{ current_user.city }}"{% end %}>
bd09b86a 221 </div>
45cfec9a
RH
222 </div>
223 <div class="column">
bd09b86a
RH
224 <div class="control">
225 <input type="text" class="input" name="post_code"
0ad196e7
MT
226 placeholder="{{ _("Post Code") }}" required
227 {% if current_user %}value="{{ current_user.postal_code }}"{% end %}>
bd09b86a 228 </div>
45cfec9a
RH
229 </div>
230 </div>
a41e6d77 231
45cfec9a
RH
232 <div class="columns">
233 <div class="column is-half">
bd09b86a
RH
234 <div class="control">
235 <div class="select">
236 <select name="country_code" required>
237 <option value="">- {{ _("Country") }} -</option>
238
239 {% for c in countries %}
240 <option value="{{ c.alpha2 }}" {% if country == c.alpha2 %}selected{% end %}>{{ c.name }}</option>
241 {% end %}
242 </select>
243 </div>
f89c578d 244 </div>
6f151c32 245 </div>
f89c578d 246
45cfec9a 247 <div class="column">
bd09b86a
RH
248 <div class="control">
249 <input type="text" class="input" name="state"
250 placeholder="{{ _("State (optional)") }}">
251 </div>
45cfec9a
RH
252 </div>
253 </div>
254
255 <div class="block">
bd09b86a
RH
256 <div class="control">
257 <input type="submit" class="button is-primary is-outlined is-fullwidth is-medium"
258 id="donate" value="{{ _("Donate Now") }}">
259 </div>
45cfec9a
RH
260 </div>
261
262 <div class="block">
263 <div class="level">
264 <div class="level-item has-text-centered">
6f151c32 265 <span class="pf pf-2x pf-american-express"></span>
45cfec9a
RH
266 </div>
267 <div class="level-item has-text-centered">
6f151c32 268 <span class="pf pf-2x pf-mastercard-alt"></span>
45cfec9a
RH
269 </div>
270 <div class="level-item has-text-centered">
6f151c32 271 <span class="pf pf-2x pf-visa"></span>
45cfec9a
RH
272 </div>
273 <div class="level-item has-text-centered">
6f151c32 274 <span class="pf pf-2x pf-sepa"></span>
f89c578d 275 </div>
45cfec9a
RH
276 <div class="level-item has-text-centered">
277 <span class="pf pf-2x pf-paypal"></span>
ef0d3151
SH
278 </div>
279 </div>
6f151c32 280 </div>
f89c578d 281
45cfec9a 282 <p class="is-size-6">
6f151c32
MT
283 The organization you will be donating to is Lightning Wire Labs GmbH who is
284 kindly handling donations for the IPFire project.
285 After clicking "Donate Now", you will be redirected to Lightning Wire Labs
286 where you will be able to complete the transaction.
287 </p>
288 </form>
d7bbf25f 289 </div>
6f151c32
MT
290 </div>
291 </div>
292 </section>
d7bbf25f 293
45cfec9a 294 <section class="section">
6f151c32 295 <div class="container">
45cfec9a
RH
296 <div class="columns">
297 <div class="column is-8">
298 <div class="block">
299 <h5 class="title is-5">Why should I donate?</h5>
95b30f84 300
45cfec9a
RH
301 <p>
302 At IPFire, we are working hard to provide you with a free firewall distribution
303 that is like no other. We release updates regularly and enhance functionality
304 to make IPFire more secure, faster and easier to use.
305 </p>
8bc72662 306
45cfec9a
RH
307 <p>
308 To achieve our high standards that we have set for ourselves, we need your help.
8bc72662 309
45cfec9a
RH
310 Only with your donation, we can get the right tools, people and utilities that
311 we need to make our work most efficient and reach our maximum potential.
8bc72662 312
45cfec9a
RH
313 Only with your donation, we can achieve our vision to make the Internet a safer
314 place that is fair for everyone and giving equal opportunities.
315 </p>
316 </div>
8bc72662 317
45cfec9a
RH
318 <div class="block">
319 <h5 class="title is-5">How much should I give?</h5>
8bc72662 320
45cfec9a
RH
321 <p>
322 We are grateful for every single donation, but of course, we appreciate
323 if you help us as much as you can.
324 </p>
8bc72662 325
45cfec9a
RH
326 <p>
327 We rely on steady contributions from companies to keep the project healthy
328 and encourage them to set up a monthly donation.
329 </p>
330 </div>
8bc72662 331
0ba47b0f 332 <div class="faq">
45cfec9a 333 <h5 class="title is-5">Frequently Asked Questions</h5>
a41e6d77 334
45cfec9a
RH
335 <div class="block">
336 <h6 class="title is-6">
337 Do you accept bank transfer via SEPA?
338 </h6>
a41e6d77 339
0ba47b0f
MT
340 <p>
341 We do accept direct transfers through SEPA. These are our bank details:
342 </p>
95b30f84 343
0ba47b0f 344 <dl>
8c89f8e3
MT
345 <dt>Bank Account Owner</dt>
346 <dd>IPFire Project</dd>
347
0ba47b0f
MT
348 <dt>IBAN</dt>
349 <dd>DE76 3605 0105 1010 8206 84</dd>
a41e6d77 350
0ba47b0f
MT
351 <dt>BIC</dt>
352 <dd>SPESDE3EXXX</dd>
353 </dl>
354 </div>
8bc72662 355
45cfec9a
RH
356 <div class="block">
357 <h6 class="title is-6">
0ba47b0f 358 Why do you need my address in order to process a donation?
45cfec9a 359 </h6>
8bc72662 360
0ba47b0f
MT
361 <p>
362 We understand that your privacy is very important.
363 </p>
bddae05d 364
0ba47b0f
MT
365 <p>
366 We ask for a minimum amount of information required to process
367 credit card donations, including billing addresses.
368 This allows our payment processor to verify your identity,
369 process your payment, and prevent fraudulent charges to your credit card.
370 </p>
bddae05d 371
0ba47b0f
MT
372 <p>
373 We keep your information private - if you have questions, please refer to
374 Lightning Wire Labs' <a href="https://www.lightningwirelabs.com/legal">Privacy Policy</a>.
375 </p>
bddae05d 376
0ba47b0f
MT
377 <p>
378 If you would rather not fill in your information on our online donation form,
379 you can send your donation via SEPA bank transfer.
380 </p>
381 </div>
8bc72662 382
45cfec9a
RH
383 <div class="block">
384 <h6 class="title is-6">
a3f22905 385 I am concerned about losing my credit card details
45cfec9a 386 </h6>
a3f22905 387
a3f22905
MT
388 <p>
389 Credit card fraud is a serious and common problem.
390 To avoid that you and we fall victim of that, we comply with
391 <a href="https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard">PCI DSS</a>,
392 which is mandatory in Europe.
393 </p>
394
395 <p>
396 That means that we never handle any credit card data
397 or store it on our systems. The entire transaction
398 is securely handled by our payment provider and our
399 systems are regularly audited to ensure that we
400 implement this standard correctly.
401 </p>
402 </div>
403
45cfec9a
RH
404 <div class="block">
405 <h6 class="title is-6">
0ba47b0f 406 Is my donation tax deductible?
45cfec9a 407 </h6>
8bc72662 408
0ba47b0f
MT
409 <p>
410 IPFire is not registered as a charitable organization and therefore donations
411 are not tax deductible in Germany or the European Union.
412 </p>
a41e6d77 413
0ba47b0f
MT
414 <p>
415 For donors outside of the European Union, please consult your tax advisor
416 about whether your donation is tax deductible.
417 </p>
418 </div>
bddae05d 419
45cfec9a
RH
420 <div class="block">
421 <h6 class="title is-6">
f04f2e81 422 What will be charged to my credit card?
45cfec9a 423 </h6>
f04f2e81 424
f04f2e81
MT
425 <p>
426 We are based in Germany. Donations by credit card from other countries
593e4b61 427 may be subject to an international payment fee charged by your credit card issuer.
f04f2e81
MT
428 This is usually a small fee around 1%, but please check with your bank
429 before donating.
430 </p>
431
432 <p>
433 If you consider this charge too high, please consider using SEPA direct
434 Debit or Bank Transfer if you can.
435 Even with this charge, it is a lot cheaper than paying the higher processing
436 fees of other payment services like PayPal which keep a lot more of the
437 donation to themselves.
438 </p>
439 </div>
440
45cfec9a
RH
441 <div class="block">
442 <h6 class="title is-6">
0ba47b0f 443 How do I cancel or change my recurring donation?
45cfec9a 444 </h6>
bddae05d 445
0ba47b0f
MT
446 <p>
447 Your credit card statements or bank statements will contain a link
448 that you can follow to cancel your donation at any time.
449 </p>
450 </div>
bddae05d 451
45cfec9a
RH
452 <div class="block">
453 <h6 class="title is-6">
0ba47b0f 454 Who can I email directly with questions about donating?
45cfec9a 455 </h6>
bddae05d 456
0ba47b0f
MT
457 <p>
458 If you have a question about donating to the IPFire Project,
459 please contact us at <a href="mailto:donate@ipfire.org">donate@ipfire.org</a>.
460 </p>
461 </div>
462 </div>
6f151c32 463 </div>
a41e6d77 464 </div>
7771acea 465 </div>
6f151c32 466 </section>
95b30f84
MT
467{% end block %}
468
469{% block javascript %}
470 <script type="text/javascript">
471 $(document).ready(function() {
45cfec9a 472 var type = $("input[name='type']");
d37d6cd2 473 var vat_number= $("input[name='vat_number']");
d1f119e3
MT
474 var amount = $("input[name='amount']");
475 var currency = $("input[name='currency']");
476 var frequency = $("input[name='frequency']");
477 var submit = $("#donate");
3d24a78c 478 var form = $("#donation-form");
6d151de3 479
d37d6cd2
MT
480 // A cache for VAT numbers
481 var vat_numbers = {};
482 var check_vat_number;
483
bd2723d4 484 // Adjust form to default currency
a6100896 485 if (currency.val() == "EUR") {
bd2723d4 486 $(".USD").hide();
a6100896 487 } else if (currency.val() == "USD") {
bd2723d4
MT
488 $(".EUR").hide();
489 }
95b30f84 490
a5f94966 491 if (amount.val()) {
45cfec9a 492 //$("#more").collapse("show");
a5f94966
MT
493 amount.change();
494 }
495
45cfec9a
RH
496 // Copy selected type
497 $("input[name='type-selector']").on("change", function() {
498 var value = $(this).val();
499 if (value) {
500 type.val(value);
501 type.change();
502 }
503 });
504
505 // Update Organization / Individual on radio-click
506 type.on("change", function() {
507 var value = $(this).val();
508
509 if (value == "individual") {
510 $(".organization").hide();
511 $(".organization-required").find("input").prop("required", false);
512
513 $(".vat-included").show();
514 $(".vat-excluded").hide();
515 } else if (value == "organization") {
516 $(".organization").show();
517 $(".organization-required").find("input").prop("required", true);
518
519 $(".vat-included").hide();
520 $(".vat-excluded").show();
521 }
522 });
523
a6100896
MT
524 $(".toggleCurrency").click(function(event) {
525 event.preventDefault();
526
527 if (currency.val() == "EUR") {
528 currency.val("USD");
95b30f84 529
95b30f84
MT
530 $(".EUR").hide();
531 $(".USD").show();
a6100896
MT
532 } else if (currency.val() == "USD") {
533 currency.val("EUR");
534
535 $(".EUR").show();
536 $(".USD").hide();
95b30f84
MT
537 }
538 });
539
45cfec9a 540
d1f119e3 541 // Copy amount when clicking on a radio buttons
6d151de3
MT
542 $("input[name='amount-selector']").on("change", function() {
543 var value = $(this).val();
544 if (value) {
545 amount.val(value);
9ae712ff 546 amount.change();
6d151de3
MT
547 }
548 });
549
d1f119e3
MT
550 // Copy frequency when clicking on a radio buttons
551 $("input[name='frequency-selector']").on("change", function() {
552 var value = $(this).val();
553 if (value) {
554 frequency.val(value);
555 }
556 });
557
a6100896 558 amount.on("change keyup mouseup", function() {
6d151de3 559 var value = $(this).val();
a5f94966 560 value = parseFloat(value);
9ae712ff
MT
561
562 // Enable/disable submit button
563 submit.prop("disabled", !value);
564
6d151de3 565 if (value) {
a6100896
MT
566 // Check matching elements
567 $("input[name='amount-selector']").each(function (i, selector) {
568 var s = $(selector);
45cfec9a 569 var b = s.parent(".button");
a5f94966 570 var v = parseFloat(s.val());
a6100896 571
a5f94966 572 if (value == v) {
45cfec9a 573 b.removeClass("is-outlined");
a6100896 574 } else {
45cfec9a 575 b.addClass("is-outlined");
a6100896
MT
576 }
577 });
9ae712ff
MT
578
579 // Update all amounts
580 $(".amount").html(value);
95b30f84
MT
581 }
582 });
9ae712ff 583
d37d6cd2
MT
584 // Check VAT numbers
585 vat_number.on("change keyup mouseup", function() {
586 if (check_vat_number)
587 clearTimeout(check_vat_number);
588
589 var input = $(this);
590 var value = input.val();
591
592 console.log(vat_numbers);
593
594 // Fetch the parent control element
595 var control = input.closest(".control");
596
597 // Remove all classes
598 input.removeClass("is-success is-danger");
599
600 // Do nothing if there is no data
601 if (!value)
602 return;
603
604 // Show that this is now processing
605 control.addClass("is-loading");
606
607 // Called when we have an API response
608 var finished = function(result) {
609 // We are no longer processing
610 control.removeClass("is-loading");
611
612 if (result.valid) {
613 input.addClass("is-success");
614 } else {
615 input.addClass("is-danger");
616 }
617
618 // Cache the result if not already done do
619 if (!vat_numbers[value])
620 vat_numbers[value] = result;
621
622 form.trigger("change");
623 };
624
625 console.log(vat_numbers[value]);
626
627 // Deliver there cached result if available
628 if (vat_numbers[value])
629 return finished(vat_numbers[value]);
630
631 // Send API request after 250ms to avoid hammering it and running into the ratelimiting
632 setTimeout(function() {
633 $.get("/donate/check-vat-number", { vat_number : value }, finished);
634 }, 250);
635 });
636
3d24a78c
MT
637 // Disable all submit buttons after the form has been submitted
638 form.one("submit", function() {
639 submit.prop("disabled", true);
9ae712ff
MT
640 });
641
45cfec9a
RH
642 // Update everything depending on type
643 type.change();
644
9ae712ff
MT
645 // Update form with initial amount
646 amount.change();
95b30f84
MT
647 });
648 </script>
1898a8bb 649{% end block %}