Skip to content

Commit

Permalink
B2B compare at price with price range (Shopify#2858)
Browse files Browse the repository at this point in the history
* Add sale badge and price-range for volume-pricing

* Add compare_at price to PDP and Feat Prod.

* Change opacity to 100% for price per item.

* Update the logic

* Hide price per item for unavailable variants.

* Remove margin for dl.

* Refactoring

* Correct a mistake in liquid.

* Change the JS logic back for updating price per item

* Add compare at to prod card. Add style to compare at
  • Loading branch information
eugenekasimov authored and SmolSoftBoi committed Feb 18, 2024
1 parent f04196e commit 6818de3
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 85 deletions.
12 changes: 12 additions & 0 deletions assets/component-volume-pricing.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,22 @@ volume-pricing show-more-button {
}

.product-form__input .price-per-item {
color: rgba(var(--color-foreground));
font-size: 1.4rem;
letter-spacing: 0.06rem;
}

.price-per-item dl {
margin: 0;
}

.price-per-item dd {
margin-left: 0;
}

.price-per-item__container .variant-item__old-price,
.price__regular .variant-item__old-price {
color: rgba(var(--color-foreground), 0.75);
font-size: 1.2rem;
letter-spacing: 0.07rem;
}
109 changes: 44 additions & 65 deletions assets/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,8 @@ class MenuDrawer extends HTMLElement {
this.querySelectorAll('summary').forEach((summary) =>
summary.addEventListener('click', this.onSummaryClick.bind(this))
);
this.querySelectorAll(
'button:not(.localization-selector):not(.country-selector__close-button):not(.country-filter__reset-button)'
).forEach((button) => button.addEventListener('click', this.onCloseButtonClick.bind(this))
this.querySelectorAll('button:not(.localization-selector)').forEach((button) =>
button.addEventListener('click', this.onCloseButtonClick.bind(this))
);
}

Expand Down Expand Up @@ -799,7 +798,7 @@ class SlideshowComponent extends SliderComponent {

setSlidePosition(position) {
if (this.setPositionTimeout) clearTimeout(this.setPositionTimeout);
this.setPositionTimeout = setTimeout(() => {
this.setPositionTimeout = setTimeout (() => {
this.slider.scrollTo({
left: position,
});
Expand Down Expand Up @@ -959,10 +958,9 @@ class VariantSelects extends HTMLElement {
this.addEventListener('change', this.onVariantChange);
}

onVariantChange(event) {
onVariantChange() {
this.updateOptions();
this.updateMasterId();
this.updateSelectedSwatchValue(event);
this.toggleAddButton(true, '', false);
this.updatePickupAvailability();
this.removeErrorMessage();
Expand All @@ -981,14 +979,7 @@ class VariantSelects extends HTMLElement {
}

updateOptions() {
this.options = Array.from(this.querySelectorAll('select, fieldset'), (element) => {
if (element.tagName === 'SELECT') {
return element.value;
}
if (element.tagName === 'FIELDSET') {
return Array.from(element.querySelectorAll('input')).find((radio) => radio.checked)?.value;
}
});
this.options = Array.from(this.querySelectorAll('select'), (select) => select.value);
}

updateMasterId() {
Expand All @@ -1001,26 +992,6 @@ class VariantSelects extends HTMLElement {
});
}

updateSelectedSwatchValue({ target }) {
const { name, value, tagName } = target;

if (tagName === 'SELECT' && target.selectedOptions.length) {
const swatchValue = target.selectedOptions[0].dataset.optionSwatchValue;
const selectedDropdownSwatchValue = this.querySelector(`[data-selected-dropdown-swatch="${name}"] > .swatch`);
if (!selectedDropdownSwatchValue) return;
if (swatchValue) {
selectedDropdownSwatchValue.style.setProperty('--swatch--background', swatchValue);
selectedDropdownSwatchValue.classList.remove('swatch--unavailable');
} else {
selectedDropdownSwatchValue.style.setProperty('--swatch--background', 'unset');
selectedDropdownSwatchValue.classList.add('swatch--unavailable');
}
} else if (tagName === 'INPUT' && target.type === 'radio') {
const selectedSwatchValue = this.querySelector(`[data-selected-swatch-value="${name}"]`);
if (selectedSwatchValue) selectedSwatchValue.innerHTML = value;
}
}

updateMedia() {
if (!this.currentVariant) return;
if (!this.currentVariant.featured_media) return;
Expand Down Expand Up @@ -1074,17 +1045,12 @@ class VariantSelects extends HTMLElement {
});
}

setInputAvailability(elementList, availableValuesList) {
elementList.forEach((element) => {
const value = element.getAttribute('value');
const availableElement = availableValuesList.includes(value);

if (element.tagName === 'INPUT') {
element.classList.toggle('disabled', !availableElement);
} else if (element.tagName === 'OPTION') {
element.innerText = availableElement
? value
: window.variantStrings.unavailable_with_option.replace('[value]', value);
setInputAvailability(listOfOptions, listOfAvailableOptions) {
listOfOptions.forEach((input) => {
if (listOfAvailableOptions.includes(input.getAttribute('value'))) {
input.innerText = input.getAttribute('value');
} else {
input.innerText = window.variantStrings.unavailable_with_option.replace('[value]', input.getAttribute('value'));
}
});
}
Expand Down Expand Up @@ -1144,18 +1110,12 @@ class VariantSelects extends HTMLElement {
const pricePerItemSource = html.getElementById(`Price-Per-Item-${this.dataset.originalSection ? this.dataset.originalSection : this.dataset.section}`);

const volumePricingDestination = document.getElementById(`Volume-${this.dataset.section}`);
const qtyRules = document.getElementById(`Quantity-Rules-${this.dataset.section}`);
const volumeNote = document.getElementById(`Volume-Note-${this.dataset.section}`);

if (volumeNote) volumeNote.classList.remove('hidden');
if (volumePricingDestination) volumePricingDestination.classList.remove('hidden');
if (qtyRules) qtyRules.classList.remove('hidden');

if (source && destination) destination.innerHTML = source.innerHTML;
if (inventorySource && inventoryDestination) inventoryDestination.innerHTML = inventorySource.innerHTML;
if (skuSource && skuDestination) {
skuDestination.innerHTML = skuSource.innerHTML;
skuDestination.classList.toggle('hidden', skuSource.classList.contains('hidden'));
skuDestination.classList.toggle('visibility-hidden', skuSource.classList.contains('visibility-hidden'));
}

if (volumePricingSource && volumePricingDestination) {
Expand All @@ -1164,15 +1124,15 @@ class VariantSelects extends HTMLElement {

if (pricePerItemSource && pricePerItemDestination) {
pricePerItemDestination.innerHTML = pricePerItemSource.innerHTML;
pricePerItemDestination.classList.toggle('hidden', pricePerItemSource.classList.contains('hidden'));
pricePerItemDestination.classList.toggle('visibility-hidden', pricePerItemSource.classList.contains('visibility-hidden'));
}

const price = document.getElementById(`price-${this.dataset.section}`);

if (price) price.classList.remove('hidden');
if (price) price.classList.remove('visibility-hidden');

if (inventoryDestination)
inventoryDestination.classList.toggle('hidden', inventorySource.innerText === '');
inventoryDestination.classList.toggle('visibility-hidden', inventorySource.innerText === '');

const addButtonUpdated = html.getElementById(`ProductSubmitButton-${sectionId}`);
this.toggleAddButton(
Expand Down Expand Up @@ -1216,19 +1176,13 @@ class VariantSelects extends HTMLElement {
const inventory = document.getElementById(`Inventory-${this.dataset.section}`);
const sku = document.getElementById(`Sku-${this.dataset.section}`);
const pricePerItem = document.getElementById(`Price-Per-Item-${this.dataset.section}`);
const volumeNote = document.getElementById(`Volume-Note-${this.dataset.section}`);
const volumeTable = document.getElementById(`Volume-${this.dataset.section}`);
const qtyRules = document.getElementById(`Quantity-Rules-${this.dataset.section}`);

if (!addButton) return;
addButtonText.textContent = window.variantStrings.unavailable;
if (price) price.classList.add('hidden');
if (inventory) inventory.classList.add('hidden');
if (sku) sku.classList.add('hidden');
if (pricePerItem) pricePerItem.classList.add('hidden');
if (volumeNote) volumeNote.classList.add('hidden');
if (volumeTable) volumeTable.classList.add('hidden');
if (qtyRules) qtyRules.classList.add('hidden');
if (price) price.classList.add('visibility-hidden');
if (inventory) inventory.classList.add('visibility-hidden');
if (sku) sku.classList.add('visibility-hidden');
if (pricePerItem) pricePerItem.classList.add('visibility-hidden');
}

getVariantData() {
Expand All @@ -1239,6 +1193,31 @@ class VariantSelects extends HTMLElement {

customElements.define('variant-selects', VariantSelects);

class VariantRadios extends VariantSelects {
constructor() {
super();
}

setInputAvailability(listOfOptions, listOfAvailableOptions) {
listOfOptions.forEach((input) => {
if (listOfAvailableOptions.includes(input.getAttribute('value'))) {
input.classList.remove('disabled');
} else {
input.classList.add('disabled');
}
});
}

updateOptions() {
const fieldsets = Array.from(this.querySelectorAll('fieldset'));
this.options = fieldsets.map((fieldset) => {
return Array.from(fieldset.querySelectorAll('input')).find((radio) => radio.checked).value;
});
}
}

customElements.define('variant-radios', VariantRadios);

class ProductRecommendations extends HTMLElement {
constructor() {
super();
Expand Down
15 changes: 14 additions & 1 deletion sections/featured-product.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,20 @@
data-variant-id="{{ product.selected_or_first_available_variant.id }}"
>
{%- if product.selected_or_first_available_variant.quantity_price_breaks.size > 0 -%}
{%- assign variant_price_compare = product.selected_or_first_available_variant.compare_at_price -%}
<div class="price-per-item">
{%- if variant_price_compare -%}
<dl class="price-per-item--current">
<dt class="visually-hidden">
{{ 'products.product.price.regular_price' | t }}
</dt>
<dd>
<s class="variant-item__old-price">
{{ variant_price_compare | money_with_currency }}
</s>
</dd>
</dl>
{%- endif -%}
{%- if current_qty_for_volume_pricing < volume_pricing_array.last.minimum_quantity -%}
{%- assign variant_price = product.selected_or_first_available_variant.price
| money_with_currency
Expand Down Expand Up @@ -326,7 +339,7 @@
</dt>
<dd>
<s class="variant-item__old-price">
{{ variant_price_compare | money }}
{{ variant_price_compare | money_with_currency }}
</s>
</dd>
<dt class="visually-hidden">
Expand Down
17 changes: 15 additions & 2 deletions sections/main-product.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,20 @@
{%- if product.quantity_price_breaks_configured? -%}
<price-per-item class="no-js-hidden" id="Price-Per-Item-{{ section.id }}" data-section-id="{{ section.id }}" data-variant-id="{{ product.selected_or_first_available_variant.id }}">
{%- if product.selected_or_first_available_variant.quantity_price_breaks.size > 0 -%}
{%- assign variant_price_compare = product.selected_or_first_available_variant.compare_at_price -%}
<div class="price-per-item">
{%- if variant_price_compare -%}
<dl class="price-per-item--current">
<dt class="visually-hidden">
{{ 'products.product.price.regular_price' | t }}
</dt>
<dd>
<s class="variant-item__old-price">
{{ variant_price_compare | money_with_currency }}
</s>
</dd>
</dl>
{%- endif -%}
{%- if current_qty_for_volume_pricing < volume_pricing_array.last.minimum_quantity -%}
{%- assign variant_price = product.selected_or_first_available_variant.price | money_with_currency -%}
<span class="price-per-item--current">{{ 'products.product.volume_pricing.price_at_each' | t: price: variant_price }}</span>
Expand All @@ -292,7 +305,7 @@
{%- endfor -%}
{%- endif -%}
</div>
{%- else -%}
{%- else -%}
{%- assign variant_price = product.selected_or_first_available_variant.price | money_with_currency -%}
{%- assign variant_price_compare = product.selected_or_first_available_variant.compare_at_price -%}
<div class="price-per-item">
Expand All @@ -303,7 +316,7 @@
</dt>
<dd>
<s class="variant-item__old-price">
{{ variant_price_compare | money }}
{{ variant_price_compare | money_with_currency }}
</s>
</dd>
<dt class="visually-hidden">
Expand Down
36 changes: 20 additions & 16 deletions snippets/card-product.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
{% endcomment %}

{{ 'component-rating.css' | asset_url | stylesheet_tag }}
{{ 'component-volume-pricing.css' | asset_url | stylesheet_tag }}

{%- if card_product and card_product != empty -%}
{%- liquid
Expand All @@ -37,8 +38,7 @@
<div class="card-wrapper product-card-wrapper underline-links-hover">
<div
class="
card
card--{{ settings.card_style }}
card card--{{ settings.card_style }}
{% if card_product.featured_media %} card--media{% else %} card--text{% endif %}
{% if settings.card_style == 'card' %} color-{{ settings.card_color_scheme }} gradient{% endif %}
{% if image_shape and image_shape != 'default' %} card--shape{% endif %}
Expand Down Expand Up @@ -199,7 +199,12 @@
</p>
{%- endif -%}

{% render 'price', product: card_product, price_class: '' %}
{% render 'price', product: card_product, price_class: '', show_compare_at_price: true %}
{%- if card_product.quantity_price_breaks_configured? -%}
<div class="card__information-volume-pricing-note">
<span class="caption">{{ 'products.product.volume_pricing.note' | t }}</span>
</div>
{%- endif -%}
</div>
</div>
{%- if show_quick_add -%}
Expand Down Expand Up @@ -259,7 +264,7 @@
</div>
</quick-add-modal>
{%- else -%}
<product-form>
<product-form data-section-id="{{ section.id }}">
{%- form 'product',
card_product,
id: product_form_id,
Expand All @@ -271,6 +276,7 @@
type="hidden"
name="id"
value="{{ card_product.selected_or_first_available_variant.id }}"
class="product-variant-id"
disabled
>
<button
Expand Down Expand Up @@ -340,26 +346,24 @@
<div class="card-wrapper product-card-wrapper underline-links-hover">
<div
class="
card
card--{{ settings.card_style }}
card--text
card card--{{ settings.card_style }}
{% if extend_height %} card--extend-height{% endif %}
{% if settings.card_style == 'card' %} color-{{ settings.card_color_scheme }} gradient{% endif %}
{% if card_product.featured_media == nil and settings.card_style == 'card' %} ratio{% endif %}
{{ horizontal_class }}
"
style="--ratio-percent: 100%;"
>
<div
class="card__inner {% if settings.card_style == 'standard' %}color-{{ settings.card_color_scheme }} gradient{% endif %}{% if settings.card_style == 'standard' %} ratio{% endif %}"
class="card__inner{% if settings.card_style == 'standard' %} color-{{ settings.card_color_scheme }} gradient{% endif %} ratio"
style="--ratio-percent: 100%;"
>
<div class="card__media">
{%- if placeholder_image -%}
{{ placeholder_image | placeholder_svg_tag: 'placeholder-svg' }}
{%- else -%}
{{ 'product-apparel-2' | placeholder_svg_tag: 'placeholder-svg' }}
{%- endif -%}
<div class="media media--transparent">
{%- if placeholder_image -%}
{{ placeholder_image | placeholder_svg_tag: 'placeholder-svg' }}
{%- else -%}
{{ 'product-apparel-2' | placeholder_svg_tag: 'placeholder-svg' }}
{% endif %}
</div>
</div>
</div>
<div class="card__content">
Expand All @@ -374,7 +378,7 @@
<span class="visually-hidden">{{ 'accessibility.vendor' | t }}</span>
<div class="caption-with-letter-spacing light">{{ 'products.product.vendor' | t }}</div>
{%- endif -%}
{% render 'price' %}
{% render 'price', show_compare_at_price: true %}
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion snippets/price.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
{%- endcomment -%}
<div class="price__regular">
{%- if product.quantity_price_breaks_configured? -%}
{%- if show_compare_at_price and compare_at_price -%}
{%- if show_compare_at_price -%}
{%- unless product.price_varies == false and product.compare_at_price_varies %}
<span class="visually-hidden visually-hidden--inline">
{{- 'products.product.price.regular_price' | t -}}
Expand Down

0 comments on commit 6818de3

Please sign in to comment.