Skip to main content

Price Summary Ready

This template shows how to build a responsive price summary pattern. Please note that the example below does not represent a real use case.

Hint: Press F on your keyboard to view both templates and components in fullscreen and ESC to exit the fullscreen mode. You can also open the template in a new browser window.


Open in new window
<!DOCTYPE html>
<html class="duet-bg-gradient duet-sticky-footer" lang="fi">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>LähiTapiola</title>
<link rel="stylesheet" href="https://cdn.duetds.com/api/fonts/3.0.36/lib/localtapiola.css" integrity="sha384-5JYmtSD7nykpUvSmTW1CHMoBDkBZUpUmG0vuh+NUVtZag3F75Kr7+/JU3J7JV6Wq" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.duetds.com/api/css/4.0.18/lib/duet.min.css" integrity="sha384-lXsZJzvyiyIDxPLVC56+vhjfm/vPD4eEAE1z2Q8niyNbr0NgPl6nxGKEkjg18yQf" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.duetds.com/api/tokens/4.0.36/lib/tokens.custom-properties.css" integrity="sha384-bdxOmb87eo3bfxU+AHyrr4fo/iBSqSRZs4tIRaXT/e/8FCLFnV3mcABYDi1/CNQU" crossorigin="anonymous" />
<script type="module" src="https://cdn.duetds.com/api/components/8.4.0/lib/duet/duet.esm.js" integrity="sha384-k6jjwTqRDqMj48MzOlZv4UbSJQpGjVArPXKS4EYcxmUU+huiJgRO+66K7KN+kohP" crossorigin="anonymous"></script>
<script nomodule src="https://cdn.duetds.com/api/components/8.4.0/lib/duet/duet.js" integrity="sha384-uWHPeiybdN7WPOxcNK/EM2ZkaVcXuGUpqYw9IFr+t6Qy6bZ2O6LAlphjvuSrrPei" crossorigin="anonymous"></script>
</head>
<body>
<style>
.campaign {
transition: 500ms ease;
max-height: 0;
opacity: 0;
padding: 0 4px 1px 1px;
visibility: hidden;
overflow: hidden;
}
.campaign.active {
max-height: 250px;
opacity: 1;
visibility: visible;
}
.alert {
transition: 300ms ease;
visibility: hidden;
transform: scale(0.9);
height: 0;
opacity: 0;
}
.alert.active {
opacity: 1;
transform: scale(0.999);
visibility: visible;
height: auto;
}
</style>

<duet-header
language="fi"
skip-to-id="#content"
contact="Ota yhteyttä"
current-href="/vakuutukset/"
items='[
{ "label": "Etusivu","href": "/" },
{ "label": "Vakuutukset", "href": "/vakuutukset/" },
{ "label": "Vahinkoasiat", "href": "#" },
{ "label": "Säästöt ja sijoitukset", "href": "#" },
{ "label": "Laskut", "href": "#", "badge": "true" },
{ "label": "Viestit", "href": "#" }
]'

language-items='[
{ "label": "Suomeksi", "country": "fi", "href": "/?lang=fi" },
{ "label": "På Svenska", "country": "sv", "href": "/?lang=sv" },
{ "label": "In English", "country": "en", "href": "/?lang=en" }
]'

contact-items='[
{ "label": "Lähetä viesti", "href": "/viestit/laheta" },
{ "label": "Avaa chat", "href": "/chat/" },
{ "label": "Yhteystiedot", "href": "/yhteystiedot/" }
]'

session='{ "label": "Kirjaudu ulos", "href": "/?logout", "type": "logout" }'
user='{ "label": "Elina", "href": "/?userId=elina" }'
>

</duet-header>
<duet-layout id="content">
<div slot="main">
<duet-tab-group>
<duet-tab selected label="default summary">
<duet-card heading="Hinta ja maksaminen" heading-level="h1" padding="large">
<duet-grid responsive breakpoint="medium" alignment="stretch">
<duet-grid-item margin="none" max-width="33.333%">
<duet-choice-group value="1" label="Haluan maksaa laskuni" direction="vertical" name="group">
<duet-choice label="1 erässä" type="radio" value="1" expand></duet-choice>
<duet-choice label="2 erässä" type="radio" value="2" expand></duet-choice>
<duet-choice label="6 erässä" type="radio" value="6" expand></duet-choice>
<duet-choice label="12 erässä" type="radio" value="12" expand></duet-choice>
</duet-choice-group>
<duet-button class="button" variation="plain" icon="messaging-discount" icon-size="large">
Onko sinulle kampanjakoodi?
</duet-button>
<div class="campaign">
<form novalidate class="form">
<duet-grid responsive breakpoint="x-large" alignment="bottom">
<duet-input class="code" label="Syötä koodi" placeholder="Kampanjakoodi" expand></duet-input>
<duet-spacer size="small" direction="horizontal"></duet-spacer>
<duet-button style="min-width: 8rem" wrapping="none" submit variation="primary" class="use-code"
>Käytä</duet-button
>

</duet-grid>
</form>
<duet-alert class="alert" variation="success">Koodi käytetty onnistuneesti!</duet-alert>
</div>
</duet-grid-item>
<duet-grid-item margin="none">
<duet-spacer size="xxx-large" direction="horizontal"></duet-spacer>
</duet-grid-item>
<duet-grid-item fill margin="none">
<duet-spacer breakpoint="medium" size="xx-large"></duet-spacer>
<duet-card padding="large">
<duet-heading level="h2" visual-level="h4">Vakuutuksen hinta</duet-heading>
<duet-table margin="none" variation="plain">
<table>
<thead>
<tr>
<th>Vakuutus</th>
<th class="duet-text-right">Hinta</th>
</tr>
</thead>
<tbody>
<tr>
<td>Omakotitalo</td>
<td class="duet-text-right duet-font-weight-semi-bold">120,00&nbsp;</td>
</tr>
<tr>
<td>Koti-irtaimisto</td>
<td class="duet-text-right duet-font-weight-semi-bold">70,00&nbsp;</td>
</tr>
<tr>
<td>Vastuu</td>
<td class="duet-text-right duet-font-weight-semi-bold">30,00&nbsp;</td>
</tr>
<tr>
<td>Oikeusturva</td>
<td class="duet-text-right duet-font-weight-semi-bold">28,00&nbsp;</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="duet-font-weight-semi-bold">Vuosimaksu yhteensä</td>
<td class="duet-text-right duet-font-weight-semi-bold duet-font-size-x-large">
<span class="total">248,00</span>&nbsp;<sup
><a class="duet-color-secondary footnote" style="text-decoration: none" href="#cite"
>*</a
></sup
>

</td>
</tr>
</tfoot>
</table>
</duet-table>
<duet-grid responsive breakpoint="medium">
<duet-grid-item fill class="duet-font-weight-semi-bold"> Maksuerä </duet-grid-item>
<duet-grid-item class="duet-font-size-large duet-font-weight-semi-bold">
<span class="price">41,33</span>&nbsp;€ / <span class="period">6</span>&thinsp;×&thinsp;vuosi
</duet-grid-item>
</duet-grid>
<duet-caption margin="none" size="small" id="cite">
<sup>*</sup> Hinta saattaa muuttua vakuutuskauden vaihtuessa.
</duet-caption>
</duet-card>
<duet-spacer size="large"></duet-spacer>
<form novalidate>
<duet-grid direction="horizontal">
<duet-grid-item margin="none">
<duet-checkbox
label="Olen tutustunut vakuutuksen ehtoihin,tuoteselosteeseen ja avaintietoihin"
label-hidden
>

</duet-checkbox>
</duet-grid-item>
<duet-grid-item fill margin="none">
<duet-paragraph>
Olen tutustunut <duet-link url="#">vakuutuksen ehtoihin</duet-link>,
<duet-link url="#">tuoteselosteeseen</duet-link> ja <duet-link url="#">avaintietoihin</duet-link>.
</duet-paragraph>
</duet-grid-item>
</duet-grid>
<duet-checkbox value="confirm" label="Vakuutan että antamani tiedot ovat oikein."> </duet-checkbox>
<duet-spacer size="large"></duet-spacer>
<duet-button submit variation="primary">Hyväksy ja osta vakuutus</duet-button>
</form>
</duet-grid-item>
</duet-grid>
</duet-card>
</duet-tab>

<duet-tab label="simple summary">
<duet-card heading="Hinta ja maksaminen" heading-level="h1" padding="large">
<duet-grid responsive breakpoint="medium" alignment="stretch">
<duet-grid-item margin="none" max-width="33.333%">
<duet-choice-group value="1" label="Haluan maksaa laskuni" direction="vertical" name="group">
<duet-choice label="1 erässä" type="radio" value="1" expand></duet-choice>
<duet-choice label="2 erässä" type="radio" value="2" expand></duet-choice>
<duet-choice label="6 erässä" type="radio" value="6" expand></duet-choice>
<duet-choice label="12 erässä" type="radio" value="12" expand></duet-choice>
</duet-choice-group>
<duet-button class="button" variation="plain" icon="messaging-discount" icon-size="large">
Onko sinulle kampanjakoodi?
</duet-button>
<div class="campaign">
<form novalidate class="form">
<duet-grid responsive breakpoint="x-large" alignment="bottom">
<duet-input class="code" label="Syötä koodi" placeholder="Kampanjakoodi" expand></duet-input>
<duet-spacer size="small" direction="horizontal"></duet-spacer>
<duet-button style="min-width: 8rem" wrapping="none" submit variation="primary" class="use-code"
>Käytä</duet-button
>

</duet-grid>
</form>
<duet-alert class="alert" variation="success">Koodi käytetty onnistuneesti!</duet-alert>
</div>
</duet-grid-item>
<duet-grid-item margin="none">
<duet-spacer size="xxx-large" direction="horizontal"></duet-spacer>
</duet-grid-item>

<duet-grid-item fill margin="none">
<duet-spacer breakpoint="medium" size="xx-large"></duet-spacer>
<duet-card padding="large">
<duet-heading level="h2" visual-level="h4"> Vakuutuksen hinta </duet-heading>
<duet-table margin="none" variation="minimal" class="price-table">
<table>
<thead>
<tr>
<th>Vakuutus</th>
<th class="duet-text-right">Hinta</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Matkustajan hoitoturva
<duet-caption margin="none">
Hinnassa on huomioitu:<br />
Omaetualennus 13%<br />
Henkilökunta-alennus 20%
</duet-caption>
</td>
<td class="duet-text-right duet-font-weight-semi-bold">120,00&nbsp;</td>
</tr>
<tr>
<td>
Matkaoikeusturvavakuutus
<duet-caption margin="none">
Hinnassa on huomioitu:<br />
Omaetualennus 13%<br />
Henkilökunta-alennus 20%
</duet-caption>
</td>
<td class="duet-text-right duet-font-weight-semi-bold">70,00&nbsp;</td>
</tr>
<tr>
<td>
Tapaturmaisen kuoleman turva
<duet-caption margin="none">
Hinnassa on huomioitu:<br />
Omaetualennus 13%<br />
Henkilökunta-alennus 20%
</duet-caption>
</td>
<td class="duet-text-right duet-font-weight-semi-bold">30,00&nbsp;</td>
</tr>
<tr>
<td>
Tapaturmaisen pysyvän haitan turva
<duet-caption margin="none">
Hinnassa on huomioitu:<br />
Omaetualennus 13%<br />
Henkilökunta-alennus 20%
</duet-caption>
</td>
<td class="duet-text-right duet-font-weight-semi-bold">28,00&nbsp;</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="duet-font-weight-semi-bold">Vuosimaksu yhteensä</td>
<td class="duet-text-right duet-font-weight-semi-bold duet-font-size-x-large">
<span class="total">248,00</span>&nbsp;
</td>
</tr>
</tfoot>
</table>
</duet-table>
<duet-grid responsive breakpoint="small">
<duet-grid-item fill class="duet-font-weight-semi-bold" margin="none"> Maksuerä </duet-grid-item>
<duet-spacer size="small" breakpoint="x-small"></duet-spacer>
<duet-grid-item class="duet-font-size-large duet-font-weight-semi-bold" margin="none">
<span class="price">200.5</span> € / <span class="period">14</span>&nbsp;×&nbsp;vuosi
</duet-grid-item>
</duet-grid>
<duet-spacer></duet-spacer>

<duet-caption> *Hinta saattaa muuttua vakuutuskauden vaihtuessa. </duet-caption>
</duet-card>
<duet-spacer size="large"></duet-spacer>
<form novalidate>
<duet-grid direction="horizontal">
<duet-grid-item margin="none">
<duet-checkbox
label="Olen tutustunut vakuutuksen ehtoihin,tuoteselosteeseen ja avaintietoihin"
label-hidden
>

</duet-checkbox>
</duet-grid-item>
<duet-grid-item fill margin="none">
<duet-paragraph>
Olen tutustunut <duet-link url="#">vakuutuksen ehtoihin</duet-link>,
<duet-link url="#">tuoteselosteeseen</duet-link> ja <duet-link url="#">avaintietoihin</duet-link>.
</duet-paragraph>
</duet-grid-item>
</duet-grid>
<duet-checkbox value="confirm" label="Vakuutan että antamani tiedot ovat oikein."> </duet-checkbox>
<duet-spacer size="large"></duet-spacer>
<duet-button submit variation="primary">Hyväksy ja osta vakuutus</duet-button>
</form>
</duet-grid-item>
</duet-grid>
</duet-card>
</duet-tab>
</duet-tab-group>
</div>
</duet-layout>
<duet-footer
logo-href="#"
language="fi"
items='[
{ "label": "Hae korvausta", "href": "#", "icon": "navigation-make-claim" },
{ "label": "Osta vakuutus", "href": "#", "icon": "action-buy-insurance" },
{ "label": "Yhteystiedot", "href": "#", "icon": "form-tel" }
]'

menu='[
{ "label": "Turvallisuus ja käyttöehdot", "href": "#" },
{ "label": "Evästeet", "href": "#" },
{ "label": "Henkilötietojen käsittely", "href": "#" }
]'

>

</duet-footer>

<script>
// Save references to components we want to adjust below
var group = document.querySelectorAll("duet-choice-group")
var button = document.querySelectorAll(".button")
var form = document.querySelectorAll(".form")
var total = 248

// Footnote click handler
document.querySelector(".footnote").addEventListener("click", function (e) {
e.preventDefault()
var el = document.getElementById("cite")
window.scrollTo(0, el.getBoundingClientRect().top + window.scrollY - 80)
})

// Listen for choice changes in the group
group.forEach(groupItem => {
groupItem.addEventListener("duetChange", function (e) {
var value = e.detail.value
document.querySelectorAll(".price").forEach(priceItem => {
priceItem.innerHTML = (total / value).toFixed(2).replace(".", ",")
})
document.querySelectorAll(".period").forEach(periodItem => {
periodItem.innerHTML = value
})
})
})

// Toggle campaign code panel on button click
button.forEach(buttonItem => {
buttonItem.addEventListener("click", function (e) {
e.preventDefault()
var closeCode = e.currentTarget.closest("duet-card")
var campaign = closeCode.querySelector(".campaign")
campaign.classList.toggle("active")
setTimeout(function () {
if (campaign.classList.contains("active")) {
closeCode.querySelector(".code").setFocus()
}
}, 300)
})
})

// When using campaign code, change UI state
form.forEach(formItem => {
formItem.addEventListener("submit", function (e) {
e.preventDefault()
var closeCard = e.currentTarget.closest("duet-card")
var closeCode = closeCard.querySelector(".code")
var closeUseCode = closeCard.querySelector(".use-code")

if (closeCode.value) {
closeUseCode.loading = true
closeCode.disabled = true
total = 198

// This timeout creates a fake loading experience
setTimeout(function () {
closeUseCode.loading = false
closeCode.disabled = true
closeCard.querySelector(".alert").classList.add("active")
closeCard.querySelector(".price").innerHTML = (total / group.value).toFixed(2).replace(".", ",")
closeCard.querySelector(".total").innerHTML = total
var markup =
"<td class='added-label'>Kampanja-ale</td><td class='added-price duet-text-right duet-font-weight-semi-bold'>-50,00&nbsp;€</td>"
var row = document.createElement("tr")
row.style.backgroundColor = "rgb(242,249,247)"
row.innerHTML = markup
closeCard.querySelector("tbody").appendChild(row)

// Make sure these get added during next tick
setTimeout(function () {
closeCard.querySelector(".added-label").setAttribute("data-heading", "Alennus")
closeCard.querySelector(".added-price").setAttribute("data-heading", "Määrä")
}, 1)
}, 1000)
} else {
alert("Syötä ensin kampanjakoodi.")
}
})
})
</script>
</body>
</html>

Integration

To install this template’s dependencies into your project, run:

npm install @duetds/components
npm install @duetds/css
npm install @duetds/fonts

For further guidelines, please see each package’s documentation.



Tutorials

Follow these practical tutorials to learn how to build simple page layouts using Duet’s CSS Framework, Web Components and other features:

Tutorials

Building Layouts

Tutorials

Using CLI Tools

Tutorials

Creating Custom Patterns

Tutorials

Server Side Rendering

Tutorials

Sharing Prototypes

Tutorials

Usage With Markdown


Troubleshooting

If you experience any issues while using a template, please head over to the Support page for more guidelines and help.