Sorry for the bad title, couldn't figure a better one.
Product Options:
[
{
"_id": "5cdd1e81e85ecc7ebb145039",
"name": "Sizes S/M - M/L - L/XL ",
"display_name": "Size",
"display_style": "rectangle",
"values": [
{
"_id": "5cdd1e81e85ecc7ebb14503a",
"label": "Small / Medium",
"option_id": "5cdd1e81e85ecc7ebb145039"
},
{
"_id": "5cdd1e81e85ecc7ebb14503b",
"label": "Large / X-Large",
"option_id": "5cdd1e81e85ecc7ebb145039"
},
{
"_id": "5da8080ea51d8207e9098875",
"label": "Medium / Large",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
]
},
{
"_id": "5cdd280ce85ecc7ebb145040",
"name": "Hat Sizes Νο 56-57 / 58-59 / 60-61",
"display_name": "Hat Size",
"display_style": "rectangle",
"values": [
{
"_id": "5cdd280ce85ecc7ebb145041",
"label": "56 / 57",
"option_id": "5cdd280ce85ecc7ebb145040"
},
{
"_id": "5cdd280ce85ecc7ebb145042",
"label": "58 / 59",
"option_id": "5cdd280ce85ecc7ebb145040"
},
{
"_id": "5cdd280ce85ecc7ebb145043",
"label": "60 / 61 ",
"option_id": "5cdd280ce85ecc7ebb145040"
}
]
}
]
Product Variants:
[
{
"_id": "5e0a02e4413f9e12f20edfb5",
"options": [
{
"option": {
"_id": "5cdd1e81e85ecc7ebb145039",
"display_name": "Size",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd1e81e85ecc7ebb14503a",
"label": "Small / Medium",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
},
{
"option": {
"_id": "5cdd280ce85ecc7ebb145040",
"display_name": "Size Hat",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd280ce85ecc7ebb145041",
"label": "56 / 57",
"option_id": "5cdd280ce85ecc7ebb145040"
}
}
]
},
{
"_id": "5e0a02e4413f9e12f20edfb6",
"options": [
{
"option": {
"_id": "5cdd1e81e85ecc7ebb145039",
"display_name": "Size",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd1e81e85ecc7ebb14503a",
"label": "Small / Medium",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
},
{
"option": {
"_id": "5cdd280ce85ecc7ebb145040",
"display_name": "Size Hat",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd280ce85ecc7ebb145042",
"label": "58 / 59",
"option_id": "5cdd280ce85ecc7ebb145040"
}
}
]
},
{
"_id": "5e0a02e4413f9e12f20edfb9",
"options": [
{
"option": {
"_id": "5cdd1e81e85ecc7ebb145039",
"display_name": "Size",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd1e81e85ecc7ebb14503b",
"label": "Large / X-Large",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
},
{
"option": {
"_id": "5cdd280ce85ecc7ebb145040",
"display_name": "Size Hat",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd280ce85ecc7ebb145042",
"label": "58 / 59",
"option_id": "5cdd280ce85ecc7ebb145040"
}
}
]
},
{
"_id": "5e0a02e4413f9e12f20edfba",
"options": [
{
"option": {
"_id": "5cdd1e81e85ecc7ebb145039",
"display_name": "Size",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd1e81e85ecc7ebb14503b",
"label": "Large / X-Large",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
},
{
"option": {
"_id": "5cdd280ce85ecc7ebb145040",
"display_name": "Size Hat",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd280ce85ecc7ebb145043",
"label": "60 / 61 ",
"option_id": "5cdd280ce85ecc7ebb145040"
}
}
]
},
{
"_id": "5e0a02e4413f9e12f20edfbc",
"options": [
{
"option": {
"_id": "5cdd1e81e85ecc7ebb145039",
"display_name": "Size",
"display_style": "rectangle"
},
"value": {
"_id": "5da8080ea51d8207e9098875",
"label": "Medium / Large",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
},
{
"option": {
"_id": "5cdd280ce85ecc7ebb145040",
"display_name": "Size Hat",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd280ce85ecc7ebb145042",
"label": "58 / 59",
"option_id": "5cdd280ce85ecc7ebb145040"
}
}
]
},
{
"_id": "5e0a02e4413f9e12f20edfbb",
"options": [
{
"option": {
"_id": "5cdd1e81e85ecc7ebb145039",
"display_name": "Size",
"display_style": "rectangle"
},
"value": {
"_id": "5da8080ea51d8207e9098875",
"label": "Medium / Large",
"option_id": "5cdd1e81e85ecc7ebb145039"
}
},
{
"option": {
"_id": "5cdd280ce85ecc7ebb145040",
"display_name": "Size Hat",
"display_style": "rectangle"
},
"value": {
"_id": "5cdd280ce85ecc7ebb145041",
"label": "56 / 57",
"option_id": "5cdd280ce85ecc7ebb145040"
}
}
]
}
]
I have this code (part of React component):
setVariant = (optionIndex, valueIndex) => {
const { product } = this.state;
const parentProduct = { ...product };
const optionValue = parentProduct.options[optionIndex].values[valueIndex];
const emptyArr = [];
parentProduct.variants.forEach(({ options }) => {
options.forEach((item) => {
if (item.value._id === optionValue._id) {
emptyArr.push(...options);
}
});
});
const updatedOptions = parentProduct.options.map((productOption) => {
const productOptions = JSON.parse(JSON.stringify(productOption));
productOptions.values = productOptions.values.map((productOptionValue) => {
productOptionValue.disabled = emptyArr.every(
({ value: { _id } }) => productOptionValue._id !== _id
);
return productOptionValue;
});
return productOptions;
});
My issue with this snippet it that it sets the disabled property correctly ex. if I choose first Size
e.x. Small/Medium
, then Size Hat
60 / 61
gets disabled and I can click the other two options. But if I click another Size Hat
58 / 59
then Large / X-Large
won't get enabled.
This is what I'm trying to achieve:
But this is what i'm getting: (when changing 56 / 57
etc. then Sizes
ex. Large/X-Large
should be enabled if found in variants array, red color represents disabled button)
You can create a map for every option's value which would have a reference on the corresponding values of other options. For example, a map for Size values should look like:
{
sizeValueIdA: [hatSizeValueA, hatSizeValueB],
sizeValueIdB: [hatSizeValueB],
sizeValueIdC: []
}
So with this map, you can easily get a list of available Hat Size values knowing selected Size's value.
This is an example of code that allows you to get a list of Hat Size values by Size value id and vice versa. I think that with this data you can easily disable options in UI if they not in these lists
const sizeToHatSize = convertOptionToValueMap(productOptions[0]);
const hatSizeToSize = convertOptionToValueMap(productOptions[1]);
productVariants.forEach(variant => {
const sizeValueId = variant.options[0].value._id;
let hatSizeValueId = variant.options[1].value._id;
sizeToHatSize[sizeValueId].push(hatSizeValueId);
hatSizeToSize[hatSizeValueId].push(sizeValueId);
});
function convertOptionToValueMap(option) {
return option.values.reduce((dict, sizeOptionValue) => {
dict[sizeOptionValue._id] = [];
return dict;
}, {});
}
describe('59543685', function() {
it('should return available Hat Sizes for selected Size', function() {
const sizeValueId = '5cdd1e81e85ecc7ebb14503a';
expect(sizeToHatSize[sizeValueId]).toEqual([
'5cdd280ce85ecc7ebb145041',
'5cdd280ce85ecc7ebb145042',
]);
});
it('should return available Sizes for selected Hat Size', function() {
const hatSizeValueId = '5cdd280ce85ecc7ebb145041';
expect(hatSizeToSize[hatSizeValueId]).toEqual([
'5cdd1e81e85ecc7ebb14503a',
'5da8080ea51d8207e9098875'
]);
});
});
In my example, I have used arrays but you can choose a map instead of array for fast checking that an option is available.
const siteToHatSize = {
sizeValueIdA: {hatSizeValueA: true, hatSizeValueB: true},
sizeValueIdB: {hatSizeValueB: true},
sizeValueIdC: {}
}
const isEnabled = siteToHatSize[selectedSizeValueId][hatSizeId] // you can use it in render function
Also, in your case, with only 2 options you can also look one the problem as a 2-dimensional matrix. Every variant is just an intersection between row(Hat Size's value) and Column(Size's value).
[ /*Small*/ /*Medium*/ /*Large*/
/*56-57*/ [ 1, 0, 1],
/*58-59*/ [ 1, 1, 0],
/*60-61*/ [ 0, 0, 1],
]
Maybe this would be more appropriate structure for you :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With