Skip to content
Snippets Groups Projects
Commit 882f024b authored by Alexa Valentová's avatar Alexa Valentová
Browse files

add nakopneme calculator

parent 402d818c
Branches
No related tags found
2 merge requests!1369add nakopneme calculator,!1368add nakopneme calculator
Pipeline #21210 passed
Showing
with 1340 additions and 37 deletions
from wagtail.blocks import CharBlock, ListBlock, RichTextBlock, StructBlock, URLBlock from django.template.defaultfilters import slugify
from wagtail.blocks import (
CharBlock,
IntegerBlock,
ListBlock,
RichTextBlock,
StructBlock,
URLBlock,
)
from wagtail.images.blocks import ImageChooserBlock from wagtail.images.blocks import ImageChooserBlock
...@@ -145,3 +153,41 @@ class NakopnemeSquareCardBlock(StructBlock): ...@@ -145,3 +153,41 @@ class NakopnemeSquareCardBlock(StructBlock):
template = ( template = (
"styleguide2/includes/molecules/boxes/nakopneme/square_flip_card_box.html" "styleguide2/includes/molecules/boxes/nakopneme/square_flip_card_box.html"
) )
class CalculatorItemBlock(StructBlock):
heading = CharBlock(label="Nadpis")
text = CharBlock(label="Text")
value = IntegerBlock(label="Hodnota (Kč)")
slug = CharBlock(label="Slug (nevyplňovat)")
def get_prep_value(self, value):
value = super().get_prep_value(value)
value["slug"] = slugify(value["heading"])
return value
class Meta:
label = "Objekt v kalkulačce"
template = "styleguide2/includes/organisms/nakopneme/calculator_item.html"
class CalculatorPayableBlock(StructBlock):
def get_prep_value(self, value):
value = super().get_prep_value(value)
value["slug"] = slugify(value["form_other"])
return value
slug = CharBlock(label="Slug (nevyplňovat)")
form_1 = CharBlock(label="Tvar slova (1)")
form_2 = CharBlock(label="Tvar slova (2)")
form_3 = CharBlock(label="Tvar slova (3)")
form_4 = CharBlock(label="Tvar slova (4)")
form_5 = CharBlock(label="Tvar slova (5)")
form_other = CharBlock(label="Tvar slova (6+)")
value = IntegerBlock(label="Hodnota (Kč)")
class Meta:
label = "Věc, za kterou by se dalo zaplatit"
...@@ -4,15 +4,18 @@ from django.db import migrations, models ...@@ -4,15 +4,18 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('nakopneme', '0026_nakopnemeformpage_nakopnemeformpageformfield'), ("nakopneme", "0026_nakopnemeformpage_nakopnemeformpageformfield"),
] ]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='nakopnemeformpage', model_name="nakopnemeformpage",
name='ecomail_newsletter_list_tags', name="ecomail_newsletter_list_tags",
field=models.CharField(default='nakopneme-petice', max_length=128, verbose_name='Ecomail NL tagy'), field=models.CharField(
default="nakopneme-petice",
max_length=128,
verbose_name="Ecomail NL tagy",
),
), ),
] ]
This diff is collapsed.
# Generated by Django 5.0.7 on 2025-06-03 17:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("nakopneme", "0028_nakopnemecalculatorpage"),
]
operations = [
migrations.RenameField(
model_name="nakopnemecalculatorpage",
old_name="under_subclaim_text",
new_name="under_subclaim_content",
),
]
# Generated by Django 5.0.7 on 2025-06-03 18:11
import wagtail.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
(
"nakopneme",
"0029_rename_under_subclaim_text_nakopnemecalculatorpage_under_subclaim_content",
),
]
operations = [
migrations.AddField(
model_name="nakopnemecalculatorpage",
name="payable_blocks",
field=wagtail.fields.StreamField(
[("calculator_payable", 7)],
blank=True,
block_lookup={
0: ("wagtail.blocks.CharBlock", ("Tvar slova (1)",), {}),
1: ("wagtail.blocks.CharBlock", ("Tvar slova (2)",), {}),
2: ("wagtail.blocks.CharBlock", ("Tvar slova (3)",), {}),
3: ("wagtail.blocks.CharBlock", ("Tvar slova (4)",), {}),
4: ("wagtail.blocks.CharBlock", ("Tvar slova (5)",), {}),
5: ("wagtail.blocks.CharBlock", ("Tvar slova (6+)",), {}),
6: ("wagtail.blocks.IntegerBlock", (), {"label": "Hodnota (Kč)"}),
7: (
"wagtail.blocks.StructBlock",
[
[
("form_1", 0),
("form_2", 1),
("form_3", 2),
("form_4", 3),
("form_5", 4),
("form_other", 5),
("value", 6),
]
],
{},
),
},
verbose_name="Za co by se dalo zaplatit",
),
),
]
...@@ -8,7 +8,7 @@ from wagtail.admin.panels import FieldPanel, InlinePanel, ObjectList, TabbedInte ...@@ -8,7 +8,7 @@ from wagtail.admin.panels import FieldPanel, InlinePanel, ObjectList, TabbedInte
from wagtail.contrib.forms.models import AbstractForm, AbstractFormField from wagtail.contrib.forms.models import AbstractForm, AbstractFormField
from wagtail.contrib.forms.panels import FormSubmissionsPanel from wagtail.contrib.forms.panels import FormSubmissionsPanel
from wagtail.contrib.routable_page.models import RoutablePageMixin, route from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.fields import StreamField from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page from wagtail.models import Page
from wagtailmetadata.models import MetadataPageMixin from wagtailmetadata.models import MetadataPageMixin
...@@ -106,6 +106,7 @@ class NakopnemeHomePage(MainHomePageMixin, EcomailNewsletterMixin, RoutablePageM ...@@ -106,6 +106,7 @@ class NakopnemeHomePage(MainHomePageMixin, EcomailNewsletterMixin, RoutablePageM
"nakopneme.NakopnemeHelpUsPage", "nakopneme.NakopnemeHelpUsPage",
"nakopneme.NakopnemeContactPage", "nakopneme.NakopnemeContactPage",
"nakopneme.NakopnemeFormPage", "nakopneme.NakopnemeFormPage",
"nakopneme.NakopnemeCalculatorPage",
] ]
### PANELS ### PANELS
...@@ -562,3 +563,82 @@ class NakopnemeFormPage( ...@@ -562,3 +563,82 @@ class NakopnemeFormPage(
form = super().get_form_class() form = super().get_form_class()
form.base_fields["captcha"] = CaptchaField(label="opište písmena z obrázku") form.base_fields["captcha"] = CaptchaField(label="opište písmena z obrázku")
return form return form
class NakopnemeCalculatorPage(
ContextMixin,
ExtendedMetadataPageMixin,
SubpageMixin,
MetadataPageMixin,
PageInMenuMixin,
Page,
):
subclaim = models.CharField(verbose_name="Subclaim", blank=True, null=True)
under_subclaim_content = StreamField(
shared_blocks.DEFAULT_CONTENT_BLOCKS,
verbose_name="Obsah pod subclaimem",
blank=True,
use_json_field=True,
)
above_money_text = models.CharField(
verbose_name="Text nad součtem",
default="Sečteno a rozkradeno",
max_length=32,
)
after_count_text = RichTextField(
verbose_name='Obsah pod "Za to jsme mohli pořídit"',
blank=True,
null=True,
)
button_text = models.CharField(
verbose_name="Nadpis tlačítka na zobrazení programu",
default="Jak na korupci",
max_length=32,
)
button_url = models.URLField(
verbose_name="URL tlačítka na zobrazení programu",
max_length=64,
default="https://nakopnemeto.pirati.cz/program/",
)
calc_blocks = StreamField(
[
("calculator_item", blocks.CalculatorItemBlock()),
],
verbose_name="Objekty v kalkulačce",
blank=True,
use_json_field=True,
)
payable_blocks = StreamField(
[
("calculator_payable", blocks.CalculatorPayableBlock()),
],
verbose_name="Za co by se dalo zaplatit",
blank=True,
use_json_field=True,
)
parent_page_types = [
"nakopneme.NakopnemeHomePage",
]
subpage_types = []
content_panels = Page.content_panels + [
FieldPanel("subclaim"),
FieldPanel("under_subclaim_content"),
FieldPanel("calc_blocks"),
FieldPanel("payable_blocks"),
FieldPanel("above_money_text"),
FieldPanel("after_count_text"),
FieldPanel("button_text"),
FieldPanel("button_url"),
]
class Meta:
verbose_name = "Kalkulačka"
{% extends "styleguide2/simple_page.html" %}
{% load wagtailcore_tags %}
{% block header %}
{% include "styleguide2/includes/organisms/header/nakopneme/simple_header.html" with title=page.title %}
{% endblock %}
{% block footer %}
{% include 'styleguide2/includes/organisms/layout/footer.html' with page=main_context.page %}
{% endblock %}
{% block inner_content %}
<div class="container--wide mb-8">
<h2 class="head-10xl mb-8">
{{ page.subclaim }}
</h2>
<div>
{% for block in page.under_subclaim_content %}
{% include_block block %}
{% endfor %}
</div>
<div class="my-8 flex flex-col gap-4">
{% for block in page.calc_blocks %}
{% include_block block %}
{% endfor %}
</div>
<h2 class="text-center head-9xl mb-4">{{ page.above_money_text }}</h2>
<div class="flex justify-center">
<div class="bg-pirati-yellow p-5 head-8xl font-alt justify-center flex min-w-96">
<div id="total" data-value="0">0 Kč</div>
</div>
</div>
<div class="mt-8 text-3xl lg:text-4xl max-w-3xl mx-auto hidden min-h-40" id="buyable-things-wrapper">
<span>Za to jsme mohli pořídit</span>
<span id="buyable-things" class="font-bold"></span><span>.</span>
</div>
<div class="prose prose-black mt-8 [&_p]:text-lg mx-auto">
{{ page.after_count_text|richtext }}
</div>
<div class="flex justify-center mt-8">
{% include 'styleguide2/includes/atoms/buttons/round_button.html' with classes="bg-black text-white text-xl" text=page.button_text url=page.button_url %}
</div>
</div>
<script>
const thingPrices = {
{% for payable in page.payable_blocks %}
"{{ payable.value.slug }}": {
value: {{ payable.value.value }},
form2: "{{ payable.value.form_2 }}",
form1: "{{ payable.value.form_1 }}",
form3: "{{ payable.value.form_3 }}",
form4: "{{ payable.value.form_4 }}",
form5: "{{ payable.value.form_5 }}",
formOther: "{{ payable.value.form_other }}"
}{% if not forloop.last %},{% endif %}
{% endfor %}
};
const buyWrapper = document.getElementById("buyable-things-wrapper");
const total = document.getElementById("total");
for (const element of document.getElementsByClassName("_calculator_item")) {
element.addEventListener(
"change",
(event) => {
let currentValue = Number(total.dataset.value);
let targetValue = Number(event.currentTarget.dataset.monetaryValue);
let finalValue = 0;
if (event.currentTarget.checked) {
finalValue = currentValue + targetValue;
} else {
finalValue = currentValue - targetValue;
}
total.dataset.value = finalValue;
let buyableThingsText = "";
let position = 0;
const thingPricesLength = Object.keys(thingPrices).length;
let foundAnything = false;
for (let [key, content] of Object.entries(thingPrices)) {
if (finalValue / content.value > 1) {
const actualCount = Math.floor(finalValue / content.value);
if (position + 1 == thingPricesLength) {
buyableThingsText += ", nebo ";
} else if (position != 0 && buyableThingsText !== "") {
buyableThingsText += ", nebo ";
}
buyableThingsText += `${actualCount} `
let usedForm = "";
switch (actualCount) {
case 1:
usedForm = content.form1;
break;
case 2:
usedForm = content.form2;
break;
case 3:
usedForm = content.form3;
break;
case 4:
usedForm = content.form4;
break;
case 5:
usedForm = content.form5;
break;
default:
usedForm = content.formOther;
break;
}
buyableThingsText += usedForm;
foundAnything = true;
}
position++;
}
if (!foundAnything) {
document.getElementById("buyable-things-wrapper").classList.add("hidden");
total.innerHTML = `${finalValue.toLocaleString()} Kč`;
return;
}
if (document.getElementById("buyable-things-wrapper").classList.contains("hidden")) {
document.getElementById("buyable-things").innerHTML = buyableThingsText;
document.getElementById("buyable-things-wrapper").classList.remove("hidden");
} else {
buyWrapper.animate([ { opacity: [0] } ], { duration: 250 });
setTimeout(() => {
document.getElementById("buyable-things").innerHTML = buyableThingsText;
buyWrapper.animate([ { opacity: [1] } ], { duration: 250 });
}, 250);
}
total.animate([ { opacity: [0] } ], { duration: 250 });
setTimeout(() => {
total.animate([ { opacity: [1] } ], { duration: 250 });
total.innerHTML = `${finalValue.toLocaleString()} Kč`;
});
}
)
}
</script>
{% endblock %}
Source diff could not be displayed: it is too large. Options to address this: view the blob.
<label for="{{ self.slug }}" class="flex justify-between items-center gap-6 p-6 bg-grey-150 hover:bg-grey-175 duration-150 group cursor-pointer">
<div class="flex flex-col gap-1">
<h3 class="font-alt text-4xl">{{ self.heading }}</h3>
<div class="text-lg">{{ self.text }}</div>
</div>
<div class="form__checkbox">
<input
id="{{ self.slug }}"
name="{{ self.slug }}"
data-monetary-value="{{ self.value }}"
type="checkbox"
class="_calculator_item !w-10 !h-10 group"
autocomplete="off"
>
</div>
</label>
context:
heading: 'Podívejte se na celý program'
subheading: 'Poslat celý program na email'
image_url: '../../../../../../../static/images/nakopneme/politicians.png'
context:
leader_id: 'ustecky'
image_url: '../../../../../static/images/nakopneme/olga.jpg'
header: 'Olga Richterová'
subheader: 'Ministr průmyslu a dopravy'
content: 'Etiam egestas wisi a erat. Integer lacinia. Sed ac dolor sit amet purus malesuada congue. Pellentesque sapien. Nulla non lectus sed nisl molestie malesuada. Fusce tellus. Sed ac dolor sit amet purus malesuada congue. Mauris suscipit, ligula sit amet pharetra semper, nibh ante cursus purus, vel sagittis velit mauris vel metus. Aenean fermentum risus id tortor. Mauris dolor felis, sagittis at, luctus sed, aliquam non, tellus. Integer vulputate sem a nibh rutrum consequat. Cras pede libero, dapibus nec.'
profile_url: '#'
social_links:
-
icon: 'facebook'
url: 'https://facebook.com'
-
icon: 'youtube'
url: 'https://facebook.com'
-
icon: 'instagram'
url: 'https://facebook.com'
context:
leader_id: 'ustecky'
leader_title: 'Ústecký kraj'
context:
heading: 'Naši lídři a lídryně'
context:
heading: 'Nakopněte to s námi'
quote_content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis ante orci, molestie vitae vehicula venenatis, tincidunt ac pede. Nam sed tellus id magna elementum tincidunt. Nullam faucibus mi quis velit. Pellentesque ipsum. Phasellus et lorem id felis nonummy placerat. Aenean placerat. Sed elit dui, pellentesque a, faucibus vel, interdum nec, diam. '
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment