From c607afccedbfb35603ae95a98ad65b4c42a4eae5 Mon Sep 17 00:00:00 2001 From: k2maan Date: Thu, 6 Oct 2022 16:09:24 +0530 Subject: [PATCH 01/11] Sort features (color, size etc) using apparel sorter. Implemented sorting on the product list page and on the product detials page based on the variant's size and color. (#2kbv95j) --- src/apparel-sorter/index.ts | 153 ++++++++++++++++++++++++++++++++++ src/main.ts | 17 ++-- src/views/product-details.vue | 33 +++++++- 3 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 src/apparel-sorter/index.ts diff --git a/src/apparel-sorter/index.ts b/src/apparel-sorter/index.ts new file mode 100644 index 000000000..696fc9c5d --- /dev/null +++ b/src/apparel-sorter/index.ts @@ -0,0 +1,153 @@ +/* ++Copyright (c) 2015, Grant Copley ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++ ++* Redistributions of source code must retain the above copyright notice, this ++ list of conditions and the following disclaimer. ++ ++* Redistributions in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ++FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ + +const regexes = [ + /^osfa.*$/i, + /^one .*$/i, + /^one$/i, + /^xxs/i, + /^xs .*$/i, + /^x sm.*$/i, + /^xs.*$/i, + /^.* xs$/i, + /^xs/i, + /^sm.*$/i, + /^.* small/i, + /^ss/i, + /^short sleeve/i, + /^ls/i, + /^long sleeve/i, + /^s$/i, + /^small.*$/i, + /^s\/.*$/i, + /^s \/.*$/i, + /^s .*$/i, + /^m$/i, + /^medium.*$/i, + /^.*med.*$/i, + /^m .*$/i, + /^m[A-Za-z]*/i, + /^M\/.*$/i, + /^l$/i, + /^.*lg.*$/i, + /^large.*$/i, + /^l .*$/i, + /^l\/.*$/i, + /^lt$/i, + /^xl.*$/i, + /^x large.*$/i, + /^.* XL$/i, + /^x-l.*$/i, + /^l[A-Za-z]*$/i, + /^petite l.*$/i, + /^1x.*$/i, + /^.* 1x$/i, + /^2x.*$/i, + /^.* 2X$/i, + /^XXL.*$/i, + /^3x.*$/i, + /^XXXL.*$/i, + /^4x.*$/i, + /^XXXXL.*$/i, + /^5x.*$/i, + /^XXXXXL.*$/i, + /^6x.*$/i, + /^XXXXXXL.*$/i, + /^7x.*$/i, + /^XXXXXXXL.*$/i, + /^8x.*$/i, + /^XXXXXXXL.*$/i, + /^9x.*$/i, + /^XXXXXXXXL.*$/i, + /^10x.*$/i, + /^XXXXXXXXXL.*$/i, + /^11x.*$/i, + /^XXXXXXXXXXL.*$/i, + /^12x.*$/i, + /^XXXXXXXXXXXL.*$/i, + /^13x.*$/i, + /^XXXXXXXXXXXXL.*$/i, + /^14x.*$/i, + /^XXXXXXXXXXXXXL.*$/i, + /^15x.*$/i, + /^XXXXXXXXXXXXXXL.*$/i, + /^16x.*$/i, + /^XXXXXXXXXXXXXXXL.*$/i, + /^17x.*$/i, + /^XXXXXXXXXXXXXXXXL.*$/i, + /^18x.*$/i, + /^XXXXXXXXXXXXXXXXXL.*$/i, +].map(function (regex, index) { + return { regex: regex, index: index }; +}); + +function findRegexMatch(patterns: any, iteration: any, size: any): any { + console.log("size", size, typeof size) + if (patterns.length - 1 >= iteration) { + if (size.search(patterns[iteration].regex) >= 0) { + return { regex: patterns[iteration].regex, index: patterns[iteration].index, size: size, sizeVal: parseInt(size) || 0 }; + } + return findRegexMatch(patterns, iteration = iteration + 1, size); + } + return { regex: "No Match", index: parseInt(size.replace(/[^\d.-]/g, '')), size: size, sizeVal: parseInt(size) || 0 }; +} + +function matchSizesWithRegexes(size: any) { + return findRegexMatch(regexes, 0, size); +} + + +function sortSizesByIndex(size1: any, size2: any) { + if (size1.index < size2.index || size1.sizeVal > 0 && size2.sizeVal > 0 && size1.sizeVal < size2.sizeVal) return -1; + if (size1.index == size2.index || size1.sizeVal > 0 && size2.sizeVal > 0 && size1.sizeVal == size2.sizeVal) return 0; + return 1; +} + +function getSize(result: any) { + return result.size; +} + +function getIndex(result: any) { + return result.index; +} + +////////////////////////////////////////////////////////////////// + +export function sortSizes(sizes: any) { + if (!sizes) { + return []; + } + return sizes + .map(matchSizesWithRegexes) + .sort(sortSizesByIndex) + .map(getSize); +} + +export function sizeIndex(size: any) { + return [size] + .map(matchSizesWithRegexes) + .map(getIndex)[0] || 0; +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index b83cb69df..c21015fcf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,7 +8,7 @@ import i18n from './i18n' import store from './store' import moment from 'moment' import "moment-timezone"; - +import { sortSizes } from "@/apparel-sorter" /* Core CSS required for Ionic components to work properly */ import '@ionic/vue/css/core.css'; @@ -84,24 +84,25 @@ app.config.globalProperties.$filters = { } }, getFeatures(featureHierarchy: any, featureKey: string) { - let featuresValue = '' + let featuresValue = '' if (featureHierarchy) { - featureHierarchy.filter((featureItem: any) => featureItem.startsWith(featureKey)).forEach((feature: any) => { + let featuresList = featureHierarchy.filter((featureItem: any) => featureItem.startsWith(featureKey)).map((feature: any) => { const featureSplit = feature ? feature.split('/') : []; const featureValue = featureSplit[2] ? featureSplit[2] : ''; - featuresValue += featuresValue.length > 0 ? ", " + featureValue : featureValue; + return featureValue; }) + featuresList = featureKey === '1/SIZE/' ? sortSizes(featuresList) : featuresList + featuresValue = featuresList.join(" "); } - // trim removes extra white space from beginning for the first feature - return featuresValue.trim(); + return featuresValue; }, getFeaturesList(featureHierarchy: any, featureKey: string) { - let featuresList = [] + let featuresList = [] as any; if (featureHierarchy) { featuresList = featureHierarchy.filter((featureItem: any) => featureItem.startsWith(featureKey)).map((feature: any) => { const featureSplit = feature ? feature.split('/') : []; const featureValue = featureSplit[2] ? featureSplit[2] : ''; - return featureValue; + return featureKey === '1/SIZE/' ? sortSizes(featuresList) : featuresList; }) } return featuresList; diff --git a/src/views/product-details.vue b/src/views/product-details.vue index ec3e9530a..39c65311e 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -116,7 +116,9 @@
- + =========={{ sortedList(current.list.items) }}----------- + +
@@ -208,6 +210,7 @@ import { mapGetters } from "vuex"; import { ProductService } from '@/services/ProductService' import moment from 'moment'; import Image from '@/components/Image.vue'; +import { sizeIndex } from "@/apparel-sorter" export default defineComponent({ name: "product-details", @@ -508,6 +511,34 @@ export default defineComponent({ }); return Promise.all(variantRequests); }, + sortedList(list: any) { + const sortableList = list.map((item: any) => { + const featureHierarchy = this.getProduct(item.groupValue).featureHierarchy; + + if (featureHierarchy) { + const feature = featureHierarchy.find((featureItem: any) => featureItem.startsWith('1/SIZE/')) + const featureSplit = feature ? feature.split('/') : []; + console.log("featureSplit", featureSplit) + // TODO Find a better way + item.size = featureSplit[2] ? featureSplit[2] : ''; + } + return item; + }) + console.log("sortableList", sortableList) + // Considered if any of the item has size it should be sorted + const isSortable = sortableList.some((item: any) => item.size); + console.log("isSortable", isSortable) + function compare(a: any, b: any) { + if (sizeIndex(a.size) < sizeIndex(b.size)) + return -1; + if (sizeIndex(a.size) > sizeIndex(b.size)) + return 1; + return 0; + } + // console.log("sortableList.sort(compare)", sortableList.sort(compare)) + // Only sort when there is size + return isSortable ? sortableList.sort(compare) : list; + } }, setup() { const store = useStore(); From 3714f04a26cd50366a9f7fef972d2bbb24d97474 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:42:13 +0530 Subject: [PATCH 02/11] Removed: unwanted console log (#2kbv95j) --- src/apparel-sorter/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/apparel-sorter/index.ts b/src/apparel-sorter/index.ts index 696fc9c5d..a03a89c45 100644 --- a/src/apparel-sorter/index.ts +++ b/src/apparel-sorter/index.ts @@ -105,7 +105,6 @@ const regexes = [ }); function findRegexMatch(patterns: any, iteration: any, size: any): any { - console.log("size", size, typeof size) if (patterns.length - 1 >= iteration) { if (size.search(patterns[iteration].regex) >= 0) { return { regex: patterns[iteration].regex, index: patterns[iteration].index, size: size, sizeVal: parseInt(size) || 0 }; From 333ca4d39741c9ca897b10e44df996e8d25108b8 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:42:25 +0530 Subject: [PATCH 03/11] Removed: unwanted console log (#2kbv95j) --- src/views/product-details.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/views/product-details.vue b/src/views/product-details.vue index 39c65311e..7cd4766b4 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -116,8 +116,6 @@
- =========={{ sortedList(current.list.items) }}----------- -
From 5946b85c5a282f9b799c9c8ab6ce1de0f4c8f44c Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:42:42 +0530 Subject: [PATCH 04/11] Removed: unwanted console log (#2kbv95j) --- src/views/product-details.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/product-details.vue b/src/views/product-details.vue index 7cd4766b4..ed04667a6 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -522,7 +522,6 @@ export default defineComponent({ } return item; }) - console.log("sortableList", sortableList) // Considered if any of the item has size it should be sorted const isSortable = sortableList.some((item: any) => item.size); console.log("isSortable", isSortable) From d9868eff70841c515e69012fb5f0974bb4c686d5 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:42:57 +0530 Subject: [PATCH 05/11] Removed: unwanted console log (#2kbv95j) --- src/views/product-details.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/product-details.vue b/src/views/product-details.vue index ed04667a6..866f46b9a 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -532,7 +532,6 @@ export default defineComponent({ return 1; return 0; } - // console.log("sortableList.sort(compare)", sortableList.sort(compare)) // Only sort when there is size return isSortable ? sortableList.sort(compare) : list; } From a82b54f3130189fcad736e9f63728b84120f84a5 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:43:20 +0530 Subject: [PATCH 06/11] Removed: unwanted console log (#2kbv95j) --- src/views/product-details.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/product-details.vue b/src/views/product-details.vue index 866f46b9a..aa71d2b08 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -524,7 +524,6 @@ export default defineComponent({ }) // Considered if any of the item has size it should be sorted const isSortable = sortableList.some((item: any) => item.size); - console.log("isSortable", isSortable) function compare(a: any, b: any) { if (sizeIndex(a.size) < sizeIndex(b.size)) return -1; From 3e39a2d14a8d21d480cab41af23b04638b1f6373 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:51:50 +0530 Subject: [PATCH 07/11] Improved: check if it is number parse and compare (#2kbv95j) --- src/views/product-details.vue | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/views/product-details.vue b/src/views/product-details.vue index aa71d2b08..43c8d34ca 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -525,9 +525,12 @@ export default defineComponent({ // Considered if any of the item has size it should be sorted const isSortable = sortableList.some((item: any) => item.size); function compare(a: any, b: any) { - if (sizeIndex(a.size) < sizeIndex(b.size)) + const isNumber = isNumeric(a.size) && isNumeric(b.size) + const aSizeIndex = a.size ? sizeIndex(a.size) : 1000; + const bSizeIndex = b.size ? sizeIndex(b.size) : 1000; + if ( (isNumber && parseFloat(a.size) < parseFloat(b.size)) || aSizeIndex < bSizeIndex) return -1; - if (sizeIndex(a.size) > sizeIndex(b.size)) + if ((isNumber && parseFloat(a.size) > parseFloat(b.size)) || aSizeIndex > bSizeIndex) return 1; return 0; } From 74e441c94d33ad438f9a4e29a87f3d411f458392 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 17:54:07 +0530 Subject: [PATCH 08/11] Improved: implemented method to check if number (#2kbv95j) --- src/views/product-details.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/views/product-details.vue b/src/views/product-details.vue index 43c8d34ca..975b1eca5 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -516,7 +516,9 @@ export default defineComponent({ if (featureHierarchy) { const feature = featureHierarchy.find((featureItem: any) => featureItem.startsWith('1/SIZE/')) const featureSplit = feature ? feature.split('/') : []; - console.log("featureSplit", featureSplit) + function isNumeric(num: any) { + return !isNaN(num) + } // TODO Find a better way item.size = featureSplit[2] ? featureSplit[2] : ''; } From 1187d7b2fe3a14e7e50eb0d7b4d93a0dcd629425 Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 18:00:39 +0530 Subject: [PATCH 09/11] Fixed: list returned instead of value (#2kbv95j) --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index c21015fcf..5d4f8908a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -102,7 +102,7 @@ app.config.globalProperties.$filters = { featuresList = featureHierarchy.filter((featureItem: any) => featureItem.startsWith(featureKey)).map((feature: any) => { const featureSplit = feature ? feature.split('/') : []; const featureValue = featureSplit[2] ? featureSplit[2] : ''; - return featureKey === '1/SIZE/' ? sortSizes(featuresList) : featuresList; + return featuresValue; }) } return featuresList; From e0078bb57405a372faea02f2f6c3d163d53c9f6d Mon Sep 17 00:00:00 2001 From: Aditya Sharma Date: Tue, 11 Oct 2022 18:01:12 +0530 Subject: [PATCH 10/11] Improved: sort list if having size (#2kbv95j) --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 5d4f8908a..55de24e6c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -105,7 +105,7 @@ app.config.globalProperties.$filters = { return featuresValue; }) } - return featuresList; + return featureKey === '1/SIZE/' ? sortSizes(featuresList) : featuresList; }, getCustomerLoyalty(orderNotes: any, cusotmerLoyaltyOptions: any) { let customerLoyalty = '' as any From ac38a9bc5f86c00849c922abede54e938fbd12ef Mon Sep 17 00:00:00 2001 From: k2maan Date: Tue, 11 Oct 2022 18:13:17 +0530 Subject: [PATCH 11/11] Resolved: typo error and isNumeric function definition placement (#2kbv95j) --- src/main.ts | 2 +- src/views/product-details.vue | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.ts b/src/main.ts index 55de24e6c..cc36132f3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -102,7 +102,7 @@ app.config.globalProperties.$filters = { featuresList = featureHierarchy.filter((featureItem: any) => featureItem.startsWith(featureKey)).map((feature: any) => { const featureSplit = feature ? feature.split('/') : []; const featureValue = featureSplit[2] ? featureSplit[2] : ''; - return featuresValue; + return featureValue; }) } return featureKey === '1/SIZE/' ? sortSizes(featuresList) : featuresList; diff --git a/src/views/product-details.vue b/src/views/product-details.vue index 975b1eca5..9528962e5 100644 --- a/src/views/product-details.vue +++ b/src/views/product-details.vue @@ -516,9 +516,6 @@ export default defineComponent({ if (featureHierarchy) { const feature = featureHierarchy.find((featureItem: any) => featureItem.startsWith('1/SIZE/')) const featureSplit = feature ? feature.split('/') : []; - function isNumeric(num: any) { - return !isNaN(num) - } // TODO Find a better way item.size = featureSplit[2] ? featureSplit[2] : ''; } @@ -526,6 +523,9 @@ export default defineComponent({ }) // Considered if any of the item has size it should be sorted const isSortable = sortableList.some((item: any) => item.size); + function isNumeric(num: any) { + return !isNaN(num) + } function compare(a: any, b: any) { const isNumber = isNumeric(a.size) && isNumeric(b.size) const aSizeIndex = a.size ? sizeIndex(a.size) : 1000;