window.is_develop=window.location.hostname.indexOf(".test")>=0||window.location.hostname.indexOf(".amazingjackie.com")>=0,window.urlParams=new URLSearchParams(window.location.search),window.pathname=window.location.pathname,window.path_parts=pathname.split("/"),window.today=new Date,window.server_media="https://testapi.amazingjackie.com/media/",window.static_path="../../static/",window.is_loading=!1,window.user_data=null,window.current_lang=path_parts.includes("en")?"en":path_parts.includes("cn")?"cn":"zh",window.current_currency="HKD",window.default_currency="HKD",window.server_currency="HKD",window.currency_rate=null,window.store_purchase_plan=null,window.store_account_data=null,window.store_setting=null,window.local_setting=null,window.mini_cart_subtotal=0,window.chat_keywords=null,window.chat_questions=null,window.offline_payment_methods=["bank_transfer","payme","fps"],window.html=document.documentElement,window.body=document.body,html.className+=" yes_js",window.canCL=body.classList,window.isIE=document.documentMode&&!/Edge/.test(ua),window.passiveIfSupported=!1;try{window.addEventListener("test",null,Object.defineProperty({},"passive",{get:function(){passiveIfSupported={passive:!0}}}))}catch(err){}window.qs=function(e,s){return e.querySelector(s)},window.qsa=function(e,s){return e.querySelectorAll(s)},window.dq=function(s){return qs(document,s)},window.dqa=function(s){return qsa(document,s)},window.gw=function(){return window.innerWidth||html.clientWidth||body.clientWidth},window.gh=function(){return window.innerHeight||html.clientHeight||body.clientHeight},window.gscr=function(){return window.scrollY||window.pageYOffset||0},window.nodeExist=function(s){return null!==s},window.hasClass=function(s,n){if(nodeExist(s))return canCL?s.classList.contains(n):new RegExp("(\\s|^)"+n+"(\\s|$)").test(s.className)},window.addClass=function(s,a){if(nodeExist(s))for(var i=0,l=a.length;i=0&&b.splice(f,1),s.className=b.join(" ")}},window.togClass=function(s,n){nodeExist(s)&&(canCL?s.classList.toggle(n):hasClass(s,n)?cutClass(s,[n]):addClass(s,[n]))},window.eachNode=function(a,fn){for(var i=0,l=a.length;i0){var d=new Date;d.setTime(d.getTime()+24*e*60*60*1e3),x="expires="+d.toUTCString()}const str=n+"="+v+";"+x+";path=/;samesite=strict;secure";return document.cookie=str,str},CookieFactory_get=function(n){for(var m=n+"=",l=decodeURIComponent(document.cookie).split(";"),i=0;ires.json()).then(data=>{if(devlog("--- GET LOCAL STORE SETTING SUCCESS ---"),devlog(data),Validator.dataValid(data)){if(local_setting=data,local_setting.themeColor){const color_theme=themeColorDetector(local_setting.themeColor);if(local_setting.darkenThemeColor)html.style.setProperty("--darken-theme-color",local_setting.darkenThemeColor);else if("light"===color_theme){const darken_theme_color=newShade(local_setting.themeColor,-20);html.style.setProperty("--darken-theme-color",darken_theme_color)}else html.style.setProperty("--darken-theme-color",local_setting.themeColor);addClass(body,[color_theme])}else if(getComputedStyle(document.body)&&getComputedStyle(document.body).getPropertyValue("--theme-color")){const theme=themeColorDetector(getComputedStyle(document.body).getPropertyValue("--theme-color"));addClass(body,[theme])}local_setting.chatbot&&local_setting.chatbot.active&&dq("#chatbot")&&(Validator.dataValid(local_setting.chatbot.keywords,!0)&&(chat_keywords=local_setting.chatbot.keywords),Validator.dataValid(local_setting.chatbot.questions,!0)&&(chat_questions=local_setting.chatbot.questions,"function"==typeof initChatbotQuestions&&initChatbotQuestions()))}else if(devlog("--- NO LOCAL SETTING ---"),getComputedStyle(document.body)&&getComputedStyle(document.body).getPropertyValue("--theme-color")){const theme=themeColorDetector(getComputedStyle(document.body).getPropertyValue("--theme-color"));addClass(body,[theme])}"function"==typeof scriptCompletedFn&&scriptCompletedFn()}).catch(()=>{if(devlog("--- NO LOCAL SETTING ---"),getComputedStyle(document.body)&&getComputedStyle(document.body).getPropertyValue("--theme-color")){const theme=themeColorDetector(getComputedStyle(document.body).getPropertyValue("--theme-color"));addClass(body,[theme])}"function"==typeof scriptCompletedFn&&scriptCompletedFn()})},themeColorDetector=function(color){return color.match(/^rgb/)?(color=color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/),r=color[1],g=color[2],b=color[3]):(color=+("0x"+color.slice(1).replace(color.length<5&&/./g,"$&$&")),r=color>>16,g=color>>8&255,b=255&color),hsp=Math.sqrt(r*r*.299+g*g*.587+b*b*.114),hsp>200?"light":"dark"},newShade=(hexColor,magnitude)=>{if(6===(hexColor=hexColor.replace("#","")).length){const decimalColor=parseInt(hexColor,16);let r=(decimalColor>>16)+magnitude;r>255&&(r=255),r<0&&(r=0);let g=(255&decimalColor)+magnitude;g>255&&(g=255),g<0&&(g=0);let b=(decimalColor>>8&255)+magnitude;return b>255&&(b=255),b<0&&(b=0),`#${(g|b<<8|r<<16).toString(16)}`}return hexColor},mergeCart=function(callback){const temp_cart_data=App.localStorage.get("temp_cart_data");if(user_data&&Validator.dataValid(temp_cart_data,!0)){let update_cart_data=[];Validator.dataValid(user_data.cart_data_list,!0)?(update_cart_data=JSON.parse(JSON.stringify(user_data.cart_data_list)),eachNode(temp_cart_data,(function(item){const exist_item=update_cart_data.find((function(e){return e.id===item.id}));exist_item?exist_item.qty+=item.qty:update_cart_data.push(item)}))):update_cart_data=temp_cart_data,App.updateCart(update_cart_data,(function(){App.updateMiniCart(),"function"==typeof callback&&callback()}),(function(){console.error("Fail to save cart data"),"function"==typeof callback&&callback()}))}else App.updateMiniCart(),"function"==typeof callback&&callback()};function addRemoveCartEvent(event_obj,retry=0){"function"==typeof gtag?gtag("event","remove_from_cart",event_obj):retry<5&&setTimeout((function(){addRemoveCartEvent(event_obj,retry+=1)}),500)}function addAddCartEvent(event_obj,retry=0){"function"==typeof gtag?gtag("event","add_to_cart",event_obj):retry<5&&setTimeout((function(){addAddCartEvent(event_obj,retry+=1)}),500)}function addAddWishlistEvent(event_obj,retry=0){"function"==typeof gtag?gtag("event","add_to_wishlist",event_obj):retry<5&&setTimeout((function(){addAddWishlistEvent(event_obj,retry+=1)}),500)}const onCartQtyChange=function(input,product_id){const cart_data=DataProcessor.getCurrentCartData();if(Validator.dataValid(cart_data,!0)){const parent=input.closest(".product-block"),target=cart_data.find((function(e){return e.id===product_id})),prev_qty=target.qty;target&&input.value&&Validator.regexNumeric(input.value)&&parseInt(input.value)>0&&(target.qty=parseInt(input.value)),App.updateCart(cart_data,(function(){mini_cart_subtotal=0;const product_id_list=cart_data.map((function(item){return item.id}));Fetcher.GetProductByIdList(product_id_list,(function(data){if(eachNode(cart_data,(function(cart_item){const product_data=data.find((function(e){return e.id===cart_item.id}));if(product_data&&!product_data.disabled&&(parseInt(product_data.inventory)>=1||product_data.unlimited_inventory)){const total_price=cart_item.qty*DataProcessor.getProductPrice(product_data);mini_cart_subtotal+=total_price}})),dq(".mini-cart .mini-cart-total")&&(dq(".mini-cart .mini-cart-total").textContent=NumberFormatter.formatMoney(mini_cart_subtotal)),qs(parent,".qty-price>.qty").textContent=target.qty,prev_qty!==target.qty){const temp_product=data.find((function(e){return e.id===product_id}));if(temp_product)if(prev_qty>target.qty){const event_obj=DataProcessor.getProductAnalysisObj(temp_product,prev_qty-target.qty);devlog("------------ Remove Cart Item Event ------------"),devlog(event_obj),addRemoveCartEvent(event_obj)}else if(prev_qty.qty").textContent=target.qty}))}),(function(){App.alert("fail",alert_dict.error_occur[current_lang])}))}},removeCartItem=function(parent,remove_item_id,product_data){const cart_data=DataProcessor.getCurrentCartData();if(Validator.dataValid(cart_data,!0)){const target=cart_data.find((function(item){return item.id===remove_item_id})),updated_cart_data=cart_data.filter((function(item){return item.id!==remove_item_id}));App.updateCart(updated_cart_data,(function(){if(product_data){mini_cart_subtotal-=target.qty*DataProcessor.getProductPrice(product_data);const event_obj=DataProcessor.getProductAnalysisObj(product_data,target.qty);devlog("------------ Remove Cart Item Event ------------"),devlog(event_obj),addRemoveCartEvent(event_obj)}addClass(parent,["remove"]),setTimeout((function(){parent.remove()}),500),dq("#head-cart-num")&&(dq("#head-cart-num").textContent=updated_cart_data.length,updated_cart_data.length>0?addClass(dq("#head-cart-num"),["show"]):cutClass(dq("#head-cart-num"),["show"])),updated_cart_data.length<=0&&dq(".mini-cart")&&cutClass(dq(".mini-cart"),["hasProduct"]),dq(".mini-cart .mini-cart-total")&&(dq(".mini-cart .mini-cart-total").textContent=NumberFormatter.formatMoney(mini_cart_subtotal))}),(function(){App.alert("fail",alert_dict.error_occur[current_lang])}))}},ValidateUser=function(validFn,inValidFn){const local_user=App.localStorage.get("user_data");local_user&&Validator.dataValid(local_user.id)&&local_user.id>-1?(App.setLoading(!0),Fetcher.GetUserDataById(local_user.id,(function(user){user_data=user,"function"==typeof validFn&&validFn(user),App.setLoading(!1)}),(function(res){App.logout(),App.setLoading(!1)}))):"function"==typeof inValidFn&&inValidFn()};this.localStorage=storage("local"),this.sessionStorage=storage("session"),this.cookies={set:function(name,data,days=0){const n=storage_name[name]?storage_name[name]:name;return CookieFactory_set(n,data,days)},get:function(name){const n=storage_name[name]?storage_name[name]:name;return CookieFactory_get(n)},remove:function(name){const n=storage_name[name]?storage_name[name]:name;document.cookie=n+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"}},this.init=function(callback){pathname.indexOf("checkout")<0&&pathname.indexOf("payment")<0&&App.sessionStorage.remove("temp_checkout_data"),insertStoreSettingScript((function(){Fetcher.GetPurchasePlan((function(){Fetcher.GetStoreAccountSetting((function(){Fetcher.GetStoreSetting((function(){if(Validator.dataValid(store_account_data.accept_language,!0)){if(!store_account_data.accept_language.includes(current_lang.toUpperCase()))return void(window.location.href=window.location.href.replace("/"+current_lang,"/"+store_account_data.accept_language[0].toLowerCase()));if(1===store_account_data.accept_language.length&&store_account_data.accept_language[0].toLowerCase()!==current_lang){const item=dq('.head-lang>.dropdown-child>li[data-lang="'+store_account_data.accept_language[0].toLowerCase()+'"]');item&&addClass(item,["show"]),cutClass(dq(".head-lang"),["hide"])}else store_account_data.accept_language.length>1?(eachNode(store_account_data.accept_language,(function(lang){const item=dq('.head-lang>.dropdown-child>li[data-lang="'+lang.toLowerCase()+'"]');item&¤t_lang!==lang.toLowerCase()&&addClass(item,["show"])})),cutClass(dq(".head-lang"),["hide"])):addClass(dq(".head-lang"),["hide"])}else addClass(dq(".head-lang"),["hide"]);Fetcher.GetCurrencyExchangeRate((function(){if(currency_rate?(default_currency=store_account_data.default_currency||server_currency,App.localStorage.get("currency")?current_currency=App.localStorage.get("currency"):(current_currency=default_currency,App.localStorage.set("currency",current_currency))):"HKD"!==App.localStorage.get("currency")&&App.localStorage.set("currency","HKD"),Validator.dataValid(store_account_data.accept_currency,!0)&¤cy_rate){const other_currencies=store_account_data.accept_currency.filter((function(currency){return currency!==current_currency}));other_currencies.length?(eachNode(other_currencies,(function(currency){const opt=document.createElement("li");opt.textContent=currency,opt.addEventListener("click",(function(){cutClass(dq(".head-currency"),["active"]),App.changeCurrency(currency)})),dq(".head-currency .currency-option").appendChild(opt)})),cutClass(dq(".head-currency"),["hide"])):addClass(dq(".head-currency"),["hide"])}else addClass(dq(".head-currency"),["hide"]);ValidateUser((function(user){dq("#head-auth-link").href=App.generateLink("/account"),dq("#head-favorite-link")&&(dq("#head-favorite-link").href=App.generateLink("/account",{tab:"favorite"})),mergeCart(callback)}),(function(res){dq("#head-auth-link").href=App.generateLink("/auth"),dq("#head-favorite-link")&&(dq("#head-favorite-link").href=App.generateLink("/auth",{tab:"favorite"})),mergeCart(callback)}))}))}))}))}))}))},this.logout=function(){const local_user=App.localStorage.get("user_data");local_user&&local_user.token?XHR.api({user_logout:JSON.stringify({validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}})},(function(result,data,response){devlog("--------- LOGOUT ---------"),App.setUser(null),window.location.href=App.generateLink("/auth")}),(function(result,data,response){devlog("--------- FAIL: LOGOUT ---------"),App.setUser(null),window.location.href=App.generateLink("/auth")})):(App.setUser(null),window.location.href=App.generateLink("/auth"))},this.changeLang=function(new_lang){if(new_lang&¤t_lang.toLowerCase()!==new_lang.toLowerCase()){const new_path=window.location.href.replace("/"+current_lang,"/"+new_lang.toLowerCase());window.location.href=new_path}},this.changeCurrency=function(new_currency){new_currency&&(App.localStorage.set("currency",new_currency),window.location.reload())},this.setLoading=function(enable_loading=!1,disable_loading_bar=!1){enable_loading?(is_loading=!0,!disable_loading_bar&&dq(".page-loading")&&addClass(dq(".page-loading"),["show"]),addClass(body,["disable-pointer"])):(is_loading=!1,dq(".page-loading")&&cutClass(dq(".page-loading"),["show"]),cutClass(body,["disable-pointer"]))},this.generateLink=function(link,query,accept_keys){let page="";if("/"!==link){const parts=link.slice(1).split("/");page+="/",page+=parts[0],parts.length>1&&(page+="/",page+=parts.slice(1).join("/"))}let queries=[];return query&&Object.keys(query)&&eachNode(Object.keys(query),(function(key){(!accept_keys||accept_keys&&accept_keys.includes(key))&&Validator.dataValid(query[key])&&queries.push(key+"="+encodeURIComponent(query[key]))})),"/"+(current_lang||"zh")+page+(queries.length?"?"+queries.join("&"):"")},this.redirect=function(url,isCanonical,useHistory,replaceState){let l=url;isCanonical||(l=App.generateLink(url)),!0===useHistory?!0===replaceState?history.replaceState(null,"",l):history.pushState(null,"",l):window.location.href=l},this.alert=function(result,main_msg,sub_msg,second=5){dq("#alert")&&qs(dq("#alert"),".main-msg")&&qs(dq("#alert"),".sub-msg")&&(qs(dq("#alert"),".main-msg").textContent="",qs(dq("#alert"),".sub-msg").textContent="",dq("#alert").setAttribute("data-status",result),main_msg&&(qs(dq("#alert"),".main-msg").textContent=main_msg),sub_msg&&(qs(dq("#alert"),".sub-msg").textContent=sub_msg),addClass(dq("#alert"),["show"]),setTimeout((function(){cutClass(dq("#alert"),["show"])}),1e3*second))},this.callEvent=function(event_name,target){const event=new Event(event_name);target.dispatchEvent(event)},this.toggleFavorite=function(product,elm){if(user_data){if(product&&elm){let type="";type=product.liked_product?"remove":"add","add"===type?Fetcher.AddToFavorite(product.product_code,(function(data){addClass(elm,["added"]),product.liked_product=!0;const event_obj=DataProcessor.getProductAnalysisObj(product);devlog("------------ Add To Wishlist Event ------------"),devlog(event_obj),addAddWishlistEvent(event_obj)})):"remove"===type&&(product.liked_product=!1,Fetcher.RemoveFromFavorite(product.product_code,(function(){pathname.indexOf("/account")>=0&&elm.closest(".product-cell")&&elm.closest(".product-cell").remove(),cutClass(elm,["added"])})))}}else App.alert("fail",alert_dict.login.required[current_lang])},this.updateMiniCart=function(){const cart_data=DataProcessor.getCurrentCartData();if(mini_cart_subtotal=0,dq("#head-cart-num")&&(dq("#head-cart-num").textContent=0,cutClass(dq("#head-cart-num"),["show"])),dq(".mini-cart .mini-cart-total")&&(dq(".mini-cart .mini-cart-total").textContent=NumberFormatter.formatMoney(0)),Validator.dataValid(cart_data,!0)&&(dq("#head-cart-num")&&(dq("#head-cart-num").textContent=cart_data.length,cart_data.length>0?addClass(dq("#head-cart-num"),["show"]):cutClass(dq("#head-cart-num"),["show"])),dq(".mini-cart"))){const product_id_list=cart_data.map((function(item){return item.id}));Fetcher.GetProductByIdList(product_id_list,(function(data){AppUI.clearNodes(dq(".mini-cart .cart-product-list")),addClass(dq(".mini-cart"),["hasProduct"]),dq(".mini-cart .cart-product-list")&&eachNode(cart_data,(function(cart_item){const product_data=data.find((function(e){return e.id===cart_item.id}));eachNode(dqa(".mini-cart .cart-product-list"),(function(container){const clone=dq(".common-template>.mini-cart-product-block>.product-block").cloneNode(!0);product_data?qs(clone,".product-name").textContent=product_data[current_lang+"_name"]:"zh"===current_lang||"cn"===current_lang?qs(clone,".product-name").textContent="失效商品":qs(clone,".product-name").textContent="Invalid Product";let is_valid_product=!0;if((!product_data||product_data.disabled||parseInt(product_data.inventory)<1&&!product_data.unlimited_inventory)&&(is_valid_product=!1),is_valid_product){const total_price=cart_item.qty*DataProcessor.getProductPrice(product_data);mini_cart_subtotal+=total_price,qs(clone,".img-container").href=App.generateProductLink(product_data),qs(clone,".qty-price>.qty").textContent=cart_item.qty,qs(clone,".qty-price>.price").textContent=NumberFormatter.formatMoney(DataProcessor.getProductPrice(product_data)),AppUIGenerator.qtySetter(qs(clone,".setter-holder"),product_data,cart_item),qs(clone,".qty-input>input").readOnly=!0,addClass(qs(clone,".qty-input>input"),["disable-pointer"]),qs(clone,".qty-input>input").addEventListener("input",(function(){onCartQtyChange(this,product_data.id)}));const attributes=DataProcessor.getProductAttrs(product_data);Validator.dataValid(attributes,!0)&&eachNode(attributes,(function(attr){const row=document.createElement("li");row.textContent=product_data[attr][current_lang],qs(clone,".product-attr").appendChild(row)})),qs(clone,".btn-remove").addEventListener("click",(function(){removeCartItem(this.closest(".product-block"),cart_item.id,product_data)}))}else addClass(clone,["disabled"]),qs(clone,".btn-remove").addEventListener("click",(function(){removeCartItem(this.closest(".product-block"),cart_item.id,null)}));AppUIGenerator.renderProductImg(product_data&&Validator.dataValid(product_data.img_url_list,!0)?server_media+product_data.img_url_list[0]:null,qs(clone,".img-container>div"),qs(clone,".img-container")),container.appendChild(clone)}))})),dq(".mini-cart .mini-cart-total")&&(dq(".mini-cart .mini-cart-total").textContent=NumberFormatter.formatMoney(mini_cart_subtotal))}),(function(){cutClass(dq(".mini-cart"),["hasProduct"]),AppUI.clearNodes(dq(".mini-cart .cart-product-list"))}))}},this.updateCart=function(cart_data,successFn,failFn){if(user_data){let upload_data={id:user_data.id,cart_data_list:cart_data||[],cart_lastUpdated:Date.now()};Fetcher.UpdateUser(upload_data,(function(data){App.localStorage.remove("temp_cart_data"),user_data=data,"function"==typeof successFn&&successFn()}),(function(res){"token verification fail"===res.data&&App.alert("fail",alert_dict.user_token_expired[current_lang]),"function"==typeof failFn&&failFn()}))}else cart_data.length<=0?App.localStorage.remove("temp_cart_data"):App.localStorage.set("temp_cart_data",cart_data),"function"==typeof successFn&&successFn()},this.addProductToCart=function(product,added_qty,callback){if(!product)return;const cart_data=DataProcessor.getCurrentCartData(),target_in_cart=cart_data.find((function(item){return item.id===product.id}));let qty=0;target_in_cart&&(qty=target_in_cart.qty),!(!parseInt(product.inventory)||qty>=parseInt(product.inventory)||added_qty&&qty+parseInt(added_qty)>parseInt(product.inventory))||product.unlimited_inventory?!0===product.additional_product&&Validator.dataValid(product.additional_product_maximum_quantity_in_order)&&parseInt(product.additional_product_maximum_quantity_in_order)>-1&&(qty>=parseInt(product.additional_product_maximum_quantity_in_order)||added_qty&&qty+parseInt(added_qty)>parseInt(product.additional_product_maximum_quantity_in_order))?App.alert("fail",alert_dict.cart.add_limit[current_lang]):(target_in_cart?target_in_cart.qty+=added_qty?parseInt(added_qty):1:cart_data.push({id:product.id,code:product.product_code,qty:added_qty?parseInt(added_qty):1}),App.updateCart(cart_data,(function(){App.updateMiniCart(),App.alert("success",alert_dict.cart.added[current_lang]),"function"==typeof callback&&callback();const event_obj=DataProcessor.getProductAnalysisObj(product,parseInt(added_qty));devlog("------------ Add Cart Item Event ------------"),devlog(event_obj),addAddCartEvent(event_obj)}),(function(){App.alert("fail",alert_dict.error_occur[current_lang],alert_dict.no_reason[current_lang]),"function"==typeof callback&&callback()}))):App.alert("fail",alert_dict.cart.out_of_stock[current_lang],alert_dict.cart.stock_number[current_lang]+product.inventory)},this.generateProductLink=function(product){if(product){if(product.meta_url)return App.generateLink("/product/"+product.meta_url);{const query={code:product.product_code,id:void 0};return product.additional_product&&(void 0!==product.id&&null!==product.id?query.id=product.id:void 0!==product.product_id&&null!==product.product_id&&(query.id=product.product_id)),App.generateLink("/product",query)}}return App.generateLink("/store")},this.setUser=function(user){if(Validator.dataValid(user)&&Validator.dataValid(user.id)){user_data=JSON.parse(JSON.stringify(user));const local_user=App.localStorage.get("user_data");let saved={id:user.id,token:user.token};!saved.token&&local_user&&(saved.token=local_user.token),App.localStorage.set("user_data",saved),dq("#head-auth-link")&&(dq("#head-auth-link").href=App.generateLink("/account")),dq("#head-favorite-link")&&(dq("#head-favorite-link").href=App.generateLink("/account",{tab:"favorite"}))}else user_data=null,App.localStorage.remove("user_data"),dq("#head-auth-link")&&(dq("#head-auth-link").href=App.generateLink("/auth")),dq("#head-favorite-link")&&(dq("#head-favorite-link").href=App.generateLink("/auth",{tab:"favorite"}))},this.mergeUserCart=function(callback){mergeCart(callback)}},window.DataProcessor={getUniqueList:function(list){if(Validator.dataValid(list,!0)){const new_list=[];return eachNode(list,(function(e){const target=new_list.filter((function(elm){return elm===e}));target.length<=0&&new_list.push(e)})),new_list}return[]},getProductPriceType:function(product){if(!product||!store_account_data)return"";const is_vip=product.enable_vip_price&&store_purchase_plan.vip_system&&store_account_data.enable_vip_system&&user_data&&user_data.vip,is_discount=product.enable_discount_price;return is_vip&&is_discount?product.discount_price>=product.vip_price?"vip_price":"discount_price":is_discount&&!is_vip?"discount_price":!is_discount&&is_vip?"vip_price":"price"},getProductPrice:function(product){const price_type=DataProcessor.getProductPriceType(product);return price_type&&Validator.dataValid(product[price_type])?parseFloat(product[price_type]):Validator.dataValid(product.price)?parseFloat(product.price):0},getProductPriceRange:function(product,original=!1){if(!product)return[];if(Validator.dataValid(product.price_datas,!0)){const list=product.price_datas.map((function(item){return!0===original?parseFloat(item.price):DataProcessor.getProductPrice(item)}));return list.sort((function(a,b){return a-b})),list}return!0===original?[parseFloat(product.price)]:[DataProcessor.getProductPrice(product)]},getProductAttrs:function(product){let result=[];return product&&(Validator.dataValid(product.custom_attribute[current_lang])&&result.push("custom_attribute"),Validator.dataValid(product.color[current_lang])&&result.push("color"),Validator.dataValid(product.size[current_lang])&&result.push("size")),result},getProductMaxQty:function(product){if(product){let inventory=product.inventory?parseInt(product.inventory):0;return product.unlimited_inventory&&(inventory=-1),!0===product.additional_product&&Validator.dataValid(product.additional_product_maximum_quantity_in_order)&&parseInt(product.additional_product_maximum_quantity_in_order)>-1?inventory>-1?Math.min(parseInt(product.additional_product_maximum_quantity_in_order),inventory):parseInt(product.additional_product_maximum_quantity_in_order):inventory}return 0},getUserFavorites:function(){if(user_data){const favorite_products=App.localStorage.get("favorite_products");if(favorite_products){const target_favorite=favorite_products.find((function(item){return item.uid===user_data.id}));if(target_favorite&&Validator.dataValid(target_favorite.product_codes,!0))return target_favorite.product_codes}}return null},getCurrentCartData:function(){return user_data&&Validator.dataValid(user_data.cart_data_list,!0)?JSON.parse(JSON.stringify(user_data.cart_data_list)):Validator.dataValid(App.localStorage.get("temp_cart_data"),!0)&&App.localStorage.get("temp_cart_data")||[]},getSearchQueryString:function(){let queries=[];return urlParams.forEach((value,key)=>{"next"!==key&&"to"!==key&&queries.push(key+"="+value)}),queries.length?"?"+queries.join("&"):""},getProductAnalysisObj:function(product,qty=1){if(product){const exact_price=DataProcessor.getProductPrice(product);let obj={currency:"HKD",value:exact_price*qty,items:[]},item={item_id:product.sku?product.sku:product.product_code,item_name:product[current_lang+"_name"],affiliation:store_account_data.store_name,index:0,item_brand:store_account_data.store_name,price:exact_price,quantity:qty};if(exact_price!==parseFloat(product.price)&&(item.discount=parseFloat(product.price)-exact_price),Validator.dataValid(product.categories,!0))for(let i=0;i0&&(item.item_variant=attrs.join(", ")),obj.items.push(item),obj}return{}}},window.AppUI={scrollToView:function(target){if(null==target)return;const y=window.scrollY,headerH=dq("header")?dq("header").getBoundingClientRect().height:0,t=y+target.getBoundingClientRect().top-headerH-30;null!=y&&gsap&&gsap.to(window,.3,{scrollTo:{y:t,autoKill:!1},ease:Power2.easeOut})},scrollToTop:function(){gsap&&gsap.to(window,.3,{scrollTo:{y:0,autoKill:!1},ease:Power2.easeOut})},isElementInViewPort:function(target){if(!target)return!1;const rect=target.getBoundingClientRect(),windowH=gh(),windowW=gw();return rect.top<=windowH&&rect.top+rect.height>=0&&rect.left<=windowW&&rect.left+rect.width>=0},fade:function(elm,className="fade",parentNode=null){let nodes=dqa("."+className);parentNode&&(nodes=qsa(parentNode,"."+className)),nodes.length&&eachNode(nodes,(function(fade){cutClass(fade,["active","show"])})),addClass(elm,["active"]),setTimeout((function(){addClass(elm,["show"])}),100)},openModal:function(modal_id){dq(".modal")&&eachNode(dqa(".modal"),(function(e){cutClass(e,["show"])})),dq("#"+modal_id)&&addClass(dq("#"+modal_id),["show"])},closeModal:function(modal_id){dq("#"+modal_id)&&cutClass(dq("#"+modal_id),["show"])},vhCSS:function(){var h=window.innerHeight;isIE||(html.style.setProperty("--vh",.01*h+"px"),html.style.setProperty("--vhfull",.01*h+"px"))},removeAllSlides:function(slider){slider&&(slider.wrapperEl?AppUI.clearNodes(slider.wrapperEl):slider.removeAllSlides(),slider.update())},buttonLoading:function(btn_id){dq("#"+btn_id)&&dq("#"+btn_id).setAttribute("data-status","loading")},buttonReset:function(btn_id){dq("#"+btn_id)&&dq("#"+btn_id).setAttribute("data-status","")},buttonDone:function(btn_id){dq("#"+btn_id)&&dq("#"+btn_id).setAttribute("data-status","done")},clearNodes:function(parent){if(parent)for(;parent.hasChildNodes();)parent.firstChild.remove()}},window.AppUIGenerator={qtySetter:function(container,product,cart_item){if(container&&product&&cart_item&&dq(".common-template>.qty-setter")){const setter=dq(".common-template>.qty-setter").cloneNode(!0),canReserve=dq("#btn-book-product")&&Validator.dataValid(store_purchase_plan.module_list,!0)&&store_purchase_plan.module_list.includes("product_booking")&&!product.additional_product;cart_item.qty&&(qs(setter,".qty-input>input").value=cart_item.qty),cart_item.qty>1&&cutClass(qs(setter,".btn-qty.minus"),["disabled"]);const max_qty=DataProcessor.getProductMaxQty(product);(-1===max_qty||cart_item.qtyinput").addEventListener("input",(function(ev){const input_value=ev.target.value;if(input_value){const parent=this.closest(".qty-setter");addClass(qs(parent,".btn-qty.add"),["disabled"]),addClass(qs(parent,".btn-qty.minus"),["disabled"]),Validator.regexNumeric(input_value)?cart_item.qty=parseInt(input_value):(ev.target.value=1,cart_item.qty=1),cart_item.qty>1&&cutClass(qs(setter,".btn-qty.minus"),["disabled"]);const max_qty=DataProcessor.getProductMaxQty(product);(-1===max_qty||cart_item.qtyinput").addEventListener("blur",(function(){const input_value=this.value;!input_value||!Validator.regexNumeric(input_value)||parseInt(input_value)<=0?(this.value=1,cart_item.qty=1):cart_item.qty=parseInt(input_value);const max_qty=DataProcessor.getProductMaxQty(product);cart_item.qty>max_qty&&(max_qty>0||0===max_qty&&!canReserve)&&(this.value=max_qty,cart_item.qty=max_qty),App.callEvent("input",qs(setter,".qty-input>input"))})),qs(setter,".btn-qty.minus").addEventListener("click",(function(){const parent=this.closest(".qty-setter"),qty_input=qs(parent,".qty-input>input");qty_input.value&&Validator.regexNumeric(qty_input.value)?parseInt(qty_input.value)>1&&(qty_input.value=parseInt(qty_input.value)-1,cart_item.qty-=1):(qty_input.value=1,cart_item.qty=1),App.callEvent("input",qty_input)})),qs(setter,".btn-qty.add").addEventListener("click",(function(){const parent=this.closest(".qty-setter"),qty_input=qs(parent,".qty-input>input"),current_qty=qty_input.value;if(current_qty&&Validator.regexNumeric(current_qty)){const max_qty=DataProcessor.getProductMaxQty(product);(-1===max_qty||parseInt(current_qty)1){const current=filter.page;for(let i=1;i<=pages;i++)1===i||i===pages?renderPage(i):pages>4?1===current?i<=3?renderPage(i):4===i&&renderPage("rest"):current===pages?i>=pages-2?renderPage(i):i===pages-3&&renderPage("rest"):(current>=3&&2===i&&renderPage("rest"),i===current-1&¤t+1===pages&&renderPage(i),i!==current&&i!==current+1||renderPage(i),i===current+1&&i<=pages-2&&renderPage("rest")):renderPage(i);addClass(paginatorNode,["show"])}else cutClass(paginatorNode,["show"])}else cutClass(paginatorNode,["show"])},tablePaginator:function(paginate_container,total_number,items_length,filter,onPageChange,paginator_temp){let template=null;if(template=paginator_temp||".common-template>.table-paginator",paginate_container&&null!==template&&dq(template)&&(AppUI.clearNodes(paginate_container),total_number>0)){const paginator=dq(template).cloneNode(!0),start_item_num=(filter.page-1)*filter.limit+1,end_item_num=(filter.page-1)*filter.limit+items_length,total_pages=Math.ceil(total_number/filter.limit);if(qs(paginator,".page-item-num")&&(qs(paginator,".page-item-num").textContent=start_item_num+" - "+end_item_num),qs(paginator,".page-num")&&(qs(paginator,".page-num").textContent=total_pages),qs(paginator,".current-page-num")&&(qs(paginator,".current-page-num").textContent=filter.page),qs(paginator,"select")){AppUI.clearNodes(qs(paginator,"select"));for(let i=1;i<=total_pages;i++){const opt=document.createElement("option");opt.value=i,opt.textContent=i,parseInt(filter.page)===i&&(opt.selected=!0,qs(paginator,"select").value=i,qs(paginator,".selected-value").textContent=i),qs(paginator,"select").appendChild(opt)}qs(paginator,"select").addEventListener("change",(function(){filter.page=parseInt(this.value),onPageChange&&onPageChange()}))}qs(paginator,"button.prev")&&(filter.page<=1&&addClass(qs(paginator,"button.prev"),["disabled"]),qs(paginator,"button.prev").addEventListener("click",(function(){if(filter.page>1){const parent=this.closest(".table-paginator");filter.page-=1,qs(parent,"select")&&(qs(parent,"select").value=filter.page,qs(parent,'select>option[value="'+filter.page+'"]').selected=!0,qs(parent,".selected-value").textContent=filter.page),qs(paginator,".current-page-num")&&(qs(paginator,".current-page-num").textContent=filter.page),onPageChange&&onPageChange()}}))),qs(paginator,"button.next")&&(filter.page>=total_pages&&addClass(qs(paginator,"button.next"),["disabled"]),qs(paginator,"button.next").addEventListener("click",(function(){if(filter.pageoption[value="'+filter.page+'"]').selected=!0,qs(parent,".selected-value").textContent=filter.page),qs(paginator,".current-page-num")&&(qs(paginator,".current-page-num").textContent=filter.page),onPageChange&&onPageChange()}}))),paginate_container.appendChild(paginator)}},imgTextLoader:function(classNames){if(dq(".common-template>.imageText-loader")){const loader=dq(".common-template>.imageText-loader").cloneNode(!0);return Validator.dataValid(classNames,!0)&&addClass(loader,classNames),loader}return null},imgTextLoaderByNum:function(loop,container,classNames){if(Validator.regexNumeric(loop)&&nodeExist(container)){AppUI.clearNodes(container);for(let i=0;i0)eachNode(list,(function(data,index){const slide=document.createElement("div");if(slide.className="swiper-slide",componentRenderer){const component=componentRenderer(data,index);slide.appendChild(component)}swiper.appendSlide(slide)})),swiper.update();else if(Validator.regexNumeric(list)){for(let i=0;i1){let isSales=!1;for(let i=0;i1&&ori_price_range[0]!==ori_price_range[ori_price_range.length-1]?AppUIGenerator.priceSepText(qs(price_container,".price"),ori_price_range):AppUIGenerator.priceSepText(qs(price_container,".price"),ori_price_range[0]),isSales){addClass(price_container,["sales"]);const discount_price_range=DataProcessor.getProductPriceRange(product);discount_price_range.length>1&&discount_price_range[0]!==discount_price_range[discount_price_range.length-1]?AppUIGenerator.priceSepText(qs(price_container,".discount-price"),discount_price_range):AppUIGenerator.priceSepText(qs(price_container,".discount-price"),discount_price_range[0])}else cutClass(price_container,["sales"])}else{const enjoy_price_type=DataProcessor.getProductPriceType(product);AppUIGenerator.priceSepText(qs(price_container,".price"),product.price),"price"===enjoy_price_type?cutClass(price_container,["sales"]):(addClass(price_container,["sales"]),AppUIGenerator.priceSepText(qs(price_container,".discount-price"),product[enjoy_price_type]))}},priceSepText:function(container,price){nodeExist(container)&&(qs(container,".currency")&&qs(container,".value")?(qs(container,".currency").textContent=NumberFormatter.getCurrencyText(),Array.isArray(price)&&price.length>0?price.length>0?qs(container,".value").textContent=NumberFormatter.getMoneyText(price[0]):qs(container,".value").textContent="-":qs(container,".value").textContent=NumberFormatter.getMoneyText(price)):Array.isArray(price)?price.length>0?(container.innerHTML=NumberFormatter.formatMoney(price[0]),price.length>1&&(container.innerHTML+=" - "+NumberFormatter.formatMoney(price[price.length-1]))):container.innerHTML="-":container.innerHTML=NumberFormatter.formatMoney(price))},attrSelector:function(attr_list,container){function renderValueGp(title,value){const gp=document.createElement("div");if(gp.className="value-gp",title){const title_container=document.createElement("span");title_container.textContent=title,gp.appendChild(title_container)}const value_container=document.createElement("span");return value_container.textContent=value,gp.appendChild(value_container),gp}function renderValueText(list){const attr_values=list.map((function(el){return el.value})).filter((function(el){return null!=el&&""!==el}));return attr_values.join(", ")}if(Validator.dataValid(attr_list,!0)&&container){attr_list.length<2&&addClass(container,["single"]);const selector=document.createElement("div");selector.className="real-selector";const selected_value=document.createElement("div");if(selected_value.className="selected-value noselect",selector.appendChild(selected_value),"merge"===container.getAttribute("data-mode")?selected_value.textContent=renderValueText(attr_list[0].list):eachNode(attr_list[0].list,(function(data){if(data.value){let opt=renderValueGp(attr_dict[data.name][current_lang],data.value);attr_list[0].list.length<2&&"custom_attribute"===data.name&&(opt=renderValueGp("",data.value)),selected_value.appendChild(opt)}})),attr_list.length>1){selected_value.addEventListener("click",(function(){togClass(this.closest(".product-attr-selector"),"active")}));const opt_list=document.createElement("ul");opt_list.className="options",selector.appendChild(opt_list),eachNode(attr_list,(function(attr){if(qs(container,"select")){const option=document.createElement("option");option.value=attr.id;const name_list=[];eachNode(attr.list,(function(data){data.value&&name_list.push(attr_dict[data.name][current_lang]+":"+data.value)})),option.textContent=name_list.join(" / "),qs(container,"select").appendChild(option)}const value=document.createElement("li");value.setAttribute("data-value",attr.id),attr.id===attr_list[0].id&&addClass(value,["selected"]),attr.disabled&&addClass(value,["disabled"]),"merge"===container.getAttribute("data-mode")?value.textContent=renderValueText(attr.list):eachNode(attr.list,(function(data){if(data.value){let opt=renderValueGp(attr_dict[data.name][current_lang],data.value);attr.list.length<2&&"custom_attribute"===data.name&&(opt=renderValueGp("",data.value)),value.appendChild(opt)}})),value.addEventListener("click",(function(){const parent=this.closest(".product-attr-selector");qs(parent,"select").value=this.getAttribute("data-value"),qs(parent,'select>option[value="'+this.getAttribute("data-value")+'"]').selected=!0,eachNode(qsa(parent,".options>li"),(function(e){cutClass(e,["selected"])})),addClass(this,["selected"]),AppUI.clearNodes(qs(parent,".selected-value")),"merge"===container.getAttribute("data-mode")?qs(parent,".selected-value").textContent=renderValueText(attr.list):eachNode(attr.list,(function(data){if(data.value){let opt=renderValueGp(attr_dict[data.name][current_lang],data.value);attr.list.length<2&&"custom_attribute"===data.name&&(opt=renderValueGp("",data.value)),qs(parent,".selected-value").appendChild(opt)}})),App.callEvent("change",qs(parent,"select")),cutClass(parent,["active"])})),opt_list.appendChild(value)}))}container.appendChild(selector)}}},window.Formatter={filter:{numOnly:function(s){return s.replace(/[^0-9]/gi,"")},alphaOnly:function(s){return s.replace(/[^a-z]/gi,"")},alphaNumeric:function(s){return s.replace(/[^a-z0-9]/gi,"")},noWhiteSpace:function(s){return s.replace(/\s/g,"")}},convert:{byte:function(n,p){if(0===n)return"0B";var p=p||1;const k=1024,s=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],i=Math.floor(Math.log(n)/Math.log(k));return parseFloat((n/Math.pow(k,i)).toFixed(p))+s[i]}},replace:{linebreak:function(s,c){return s.replace(/(?:\r\n|\r|\n)/g,c||"
")}},separator:function(n,c,l){var l=l||3,r=new RegExp("\\B(?=(\\d{"+l+"})+(?!\\d))","g"),p=n.toString().split(".");return p[0]=p[0].replace(r,c||","),p.join(".")},pad:function(n,l,c,r,b){var s=n.toString(),l=l||2,r=!1!==r,b=!1!==b;if(s.length>0){var p="";for(isNaN(n)||"-"!=s.charAt(0)||(p="-",s=s.substring(1));s.length=0&&(format_date=format_date.replace("YYYY",str.substring(0,4))),format_date.indexOf("MM")>=0&&(format_date=format_date.replace("MM",str.substring(5,7))),format_date.indexOf("DD")>=0&&(format_date=format_date.replace("DD",str.substring(8,10)));const date=DateFormatter.convertStrToDate(str);return format_date.indexOf("DAY")>=0&&(format_date=format_date.replace("DAY",DateFormatter.formatDay(date.getDay()))),format_date}return date_str}return str},formatDay:function(day,format){const format_days={zh_short:["日","一","二","三","四","五","六"],zh_long:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],en_short:["Sun","Mon","Tue","Wed","Thu","Fir","Sat"],en_long:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]};let day_string=null;if(Validator.regexNumeric(day)){let d=parseInt(day);return(d<0||d>6)&&(d=0),Validator.dataValid(format)&&(day_string=format_days[current_lang+"_"+format]),Validator.dataValid(day_string)||(day_string="zh"===current_lang?format_days.zh_long:format_days.en_long),day_string[d]}return""},formatDateInHumanText:function(date_str,hide_year,lang){if(date_str&&Validator.regexDateStr(date_str)){let convert_lang=lang||current_lang;if("zh"===convert_lang||"cn"===convert_lang){let str=date_str.substring(5,7)+"月"+date_str.substring(8,10)+"日";return(hide_year?"":date_str.substring(0,4)+"年")+str}{let month,month_str="",str;switch(parseInt(date_str.substring(5,7))){case 1:month_str="January";break;case 2:month_str="February";break;case 3:month_str="March";break;case 4:month_str="April";break;case 5:month_str="May";break;case 6:month_str="June";break;case 7:month_str="July";break;case 8:month_str="August";break;case 9:month_str="September";break;case 10:month_str="October";break;case 11:month_str="November";break;case 12:month_str="December"}return date_str.substring(8,10)+" "+month_str+(hide_year?"":", "+date_str.substring(0,4))}}return date_str},isBeforeDate:function(main_date,compare_date){if(compare_date.getFullYear()main_date.getFullYear())return!0;if(compare_date.getFullYear()===main_date.getFullYear()){if(compare_date.getMonth()>main_date.getMonth())return!0;if(compare_date.getMonth()===main_date.getMonth()&&compare_date.getDate()>main_date.getDate())return!0}return!1},isEqualDate:function(main_date,compare_date){return main_date.getFullYear()===compare_date.getFullYear()&&main_date.getMonth()===compare_date.getMonth()&&main_date.getDate()===compare_date.getDate()}},window.NumberFormatter={roundUp:function(number,decPlace){if(Validator.regexFloat(number)||Validator.regexNumeric(number)){if(Validator.dataValid(decPlace)){const multiplier=Math.pow(10,decPlace||0);return Math.ceil(parseFloat(number)*multiplier)/multiplier}return Math.ceil(parseFloat(number))}return number},round:function(number,decPlace){if(Validator.regexFloat(number)||Validator.regexNumeric(number)){if(Validator.dataValid(decPlace)){const multiplier=Math.pow(10,decPlace||0);return Math.round(parseFloat(number)*multiplier)/multiplier}return Math.round(parseFloat(number))}return number},getCurrencyText:function(originalSign=!1){switch(current_currency){case"HKD":return originalSign?"HKD":"HK$";case"USD":return originalSign?"USD":"US$";case"TWD":return originalSign?"TWD":"NT$";default:return"$"}},getMoneyText:function(number){let n=number||0;const converted_number=NumberFormatter.convertCurrency(current_currency,n);return Formatter.separator(NumberFormatter.round(parseFloat(converted_number),1).toFixed(2))},formatMoney:function(number,originalSign=!1){return NumberFormatter.getCurrencyText(originalSign)+NumberFormatter.getMoneyText(number)},convertCurrency:function(new_currency,number){return currency_rate&&server_currency!==new_currency&&Validator.dataValid(currency_rate[server_currency])&&Validator.dataValid(currency_rate[new_currency])?parseFloat(number)*(currency_rate[new_currency]/currency_rate[server_currency]):parseFloat(number)}};const KEYS_CODE={delete:46,backspace:8,insert:45,arrow_left:37,arrow_up:38,arrow_right:39,arrow_down:40,space:32,enter:13,tab:9,shift:16,ctrl:17,alt:18},KEYS_CODE_NUM_START=48,KEYS_CODE_NUM_END=57,KEYS_CODE_NUMPAD_START=96,KEYS_CODE_NUMPAD_END=105;function backSpaceOverride(e,caretPos,caretEnd,separator){var str=e.value,caretSet=caretPos;if(caretPos==caretEnd){if(caretPos>0){var char=str.charAt(caretPos-1);e.value=char!=separator?str.slice(0,caretPos-1)+str.slice(caretPos):str.slice(0,caretPos-2)+str.slice(caretPos),caretSet=caretPos-1}}else e.value=str.slice(0,caretPos)+str.slice(caretEnd);if("createEvent"in document){var event=document.createEvent("Event");event.initEvent("input",!0,!0),e.dispatchEvent(event)}else e.fireEvent("oninput");e.focus(),e.setSelectionRange(caretSet,caretSet)}function deleteOverride(e,caretPos,caretEnd,separator){var str=e.value,char=str.charAt(caretPos);if(caretPos==caretEnd?(e.value=char!=separator?str.slice(0,caretPos)+str.slice(caretPos+1):str.slice(0,caretPos)+str.slice(caretPos+2),e.focus(),e.setSelectionRange(caretPos,caretPos)):e.value=str.slice(0,caretPos)+str.slice(caretEnd),"createEvent"in document){var event=document.createEvent("Event");event.initEvent("input",!0,!0),e.dispatchEvent(event)}else e.fireEvent("oninput");e.focus(),e.setSelectionRange(caretPos,caretPos)}window.AuthChecking=function(noUserFn,hasUserFn){const local_user=App.localStorage.get("user_data");local_user&&Validator.dataValid(local_user.id)&&local_user.id>-1?hasUserFn&&hasUserFn():noUserFn&&noUserFn()},window.Validator={dataValid:function(elm,check_length){return null!=elm&&""!==elm&&(!check_length||Array.isArray(elm)&&elm.length>0&&null!==elm[0]&&void 0!==elm[0])},regexNumeric:function(s){return/^[0-9]+$/i.test(s)},regexFloat:function(s){return/^[0-9.]+$/i.test(s)},regexAlphanumeric:function(s){return/^[a-zA-Z0-9]+$/i.test(s)},regexIdNum:function(s){return/^[a-zA-Z0-9]{8,9}$/i.test(s)},regexDateStr:function(s){return/^([0-9]{4}-[0-9]{2}-[0-9]{2})$/.test(s)},regexFullDateStr:function(s){return/^([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)$/.test(s)},regexAge:function(s){return/^([1-9]{1}[0-9]{0,1}|[1][0-3][0-9])$/.test(s)},regexEmail:function(email){return/^(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/.test(email)},regexIntlPhone:function(n){return/([0-9\s\-]{7,})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/.test(n)},regexHKPhone:function(n){return/^[2-9][0-9]{7}$/.test(n)},regexPW:function(s){return/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(s)},validateUsername:function(name){let isValidUsername=!0;const str=name.trim();for(i=0;i=48&&key<=57||key>=96&&key<=105},isFunctionKey:function(key){return key===KEYS_CODE.delete||key===KEYS_CODE.backspace||key===KEYS_CODE.tab},isValidAdditionalItem:function(item,cart_items_data,subtotal_wo_order_total_additional_item){if(item.additional_product){if("product"===item.addition_require_type&&Validator.dataValid(item.addition_require_product,!0)){const required_products=cart_items_data.filter((function(e){return item.addition_require_product.includes(e.code)}));if(required_products.length<=0)return!1}else if("order_total"===item.addition_require_type&&item.addition_require_order_amount&&subtotal_wo_order_total_additional_item0&&!accepted_types.includes(file_type.toLowerCase()))return App.alert("fail",alert_dict.upload.fail[current_lang],alert_dict.upload.format[current_lang]+accepted_types.join("/")),!1;if(limit){const size_limit=1024*parseInt(limit)*1024;if(file.size>size_limit)return App.alert("fail",alert_dict.upload.fail[current_lang],alert_dict.upload.size[current_lang]),!1}}return!0}},window.Fetcher=new function(){const validateUploadData=function(must_list,obj){if(!obj)return!1;if(Validator.dataValid(must_list,!0)){let valid=!0;return eachNode(must_list,(function(e){void 0===obj[e]&&(valid=!1)})),valid}return!0};this.GetPurchasePlan=function(callback){App.setLoading(!0),XHR.api({get_current_purchased_plan_exluding_disabled_by_application_key:JSON.stringify({application_key:app_key})},(function(result,data,response){Validator.dataValid(data)&&Validator.dataValid(data.plan_data)&&!data.plan_data.disabled?(devlog("--------- GET PURCHASE PLAN ---------"),store_purchase_plan=JSON.parse(JSON.stringify(data.plan_data)),"function"==typeof callback&&callback(),App.setLoading(!1)):window.location.href="/404error"}),(function(result,data,response){window.location.href="/404error"}))},this.GetStoreAccountSetting=function(callback){App.setLoading(!0),XHR.api({get_store_account_data_excluding_disabled_by_application_key:JSON.stringify({application_key:app_key})},(function(result,data,response){Validator.dataValid(data)&&!data.disabled?(devlog("--------- GET STORE ACCOUNT SETTING ---------"),store_account_data=JSON.parse(JSON.stringify(data)),"function"==typeof callback&&callback(),App.setLoading(!1)):window.location.href="/404error"}),(function(result,data,response){window.location.href="/404error"}))},this.GetStoreSetting=function(callback){App.setLoading(!0),XHR.api({get_store_website_data_by_application_key:JSON.stringify({application_key:app_key})},(function(result,data,response){Validator.dataValid(data)&&!data.disabled?(devlog("--------- GET STORE SETTING ---------"),store_setting=JSON.parse(JSON.stringify(data)),"function"==typeof callback&&callback(),App.setLoading(!1)):window.location.href="/404error"}),(function(result,data,response){window.location.href="/404error"}))},this.GetCurrencyExchangeRate=function(callback){XHR.api({get_currency_exchange:JSON.stringify({})},(function(result,data,response){devlog("--------- GET CURRENCY EXCHANGE RATE ---------"),Validator.dataValid(data)&&(currency_rate=JSON.parse(JSON.stringify(data))),"function"==typeof callback&&callback()}),(function(result,data,response){devlog("--------- !!FAIL: GET CURRENCY EXCHANGE RATE ---------"),"function"==typeof callback&&callback()}))},this.UploadBase64File=function(upload_data,successFn,failFn){const must_keys=["file_type","base64"];if(!validateUploadData(must_keys,upload_data))return console.error("UploadBase64File: value missing"),App.alert("fail",alert_dict.upload.fail[current_lang],alert_dict.error_occur[current_lang]+" (value missing)"),void("function"==typeof failFn&&failFn(null));const local_user=App.localStorage.get("user_data");if(!(upload_data.guest_email||local_user&&local_user.token))return App.alert("fail",alert_dict.upload.fail[current_lang],alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn(null));let final_upload_data={file_name:""};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];user_data&&(final_upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key}),final_upload_data.guest_email&&delete final_upload_data.guest_email,XHR.api({upload_base64_file_to_server:JSON.stringify(final_upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- UPLOAD FILE ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: UPLOAD FILE (NULL) ---------"),App.alert("fail",alert_dict.upload.fail[current_lang]),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UPLOAD FILE ---------");let msg="";switch(data){case"token verification fail":msg=alert_dict.user_token_expired[current_lang];break;default:msg=alert_dict.error_occur[current_lang]+" ("+JSON.stringify(data)+")"}App.alert("fail",alert_dict.upload.fail[current_lang],msg),"function"==typeof failFn&&failFn(response)}))},this.NewEnquiry=function(upload_data,successFn,failFn){const must_list=["name","phone","email","content"];if(!validateUploadData(must_list,upload_data))return console.error("NewEnquiry: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));upload_data.application_key=app_key,XHR.api({new_enquiry:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- ADD NEW ENQUIRY ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: ADD NEW ENQUIRY (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: ADD NEW ENQUIRY ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetUserDataById=function(user_id,successFn,failFn,getFavorites=!1){if(!Validator.dataValid(user_id))return console.error('GetUserDataById: "id" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn(null));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn(null));let upload_data={application_key:app_key,id:parseInt(user_id),validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}};getFavorites&&(upload_data.get_like_list=!0),XHR.api({get_user_data_by_application_key_and_id:JSON.stringify(upload_data)},(function(result,data,response){data&&!data.disabled?(devlog("--------- GET USER ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET USER (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET USER ---------"),"token verification fail"===data&&App.alert("fail",alert_dict.user_token_expired[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.GetTotalCompletedOrderAmountByUserId=function(user_id,successFn,failFn){if(!Validator.dataValid(user_id))return console.error('GetTotalCompletedOrderAmountByUserId: "user_id" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn(null));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void(failFn&&failFn(null));XHR.api({get_user_total_amount_of_completed_order_by_user_id:JSON.stringify({user_id:parseInt(user_id),application_key:app_key,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}})},(function(result,data,response){data&&Validator.dataValid(data.total_amount)?(devlog("--------- GET TOTAL ORDER AMOUNT BY USER ID ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET TOTAL ORDER AMOUNT BY USER ID (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET TOTAL ORDER AMOUNT BY USER ID ---------"),"function"==typeof failFn&&failFn(response)}))},this.UpdateUser=function(upload_data,successFn,failFn){const must_keys=["id"];if(!validateUploadData(must_keys,upload_data))return console.error("UpdateUser: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn(null));upload_data.application_key=app_key,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key},XHR.api({update_user:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- UPDATE USER ---------"),App.setUser(data),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: UPDATE USER (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UPDATE USER ---------"),"function"==typeof failFn&&failFn(response)}))},this.Register=function(upload_data,successFn,failFn){const must_keys=["email","password"];if(!validateUploadData(must_keys,upload_data))return console.error("Register: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));upload_data.application_key=app_key,XHR.api({new_user:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- REGISTER ---------"),App.setUser(data),successFn?successFn():setTimeout((function(){window.location.href=App.generateLink("/account")}),1e3)):(devlog("--------- !!FAIL: REGISTER (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: REGISTER ---------");let alert_msg="";switch(data){case"email registered":alert_msg=alert_dict.register.email_used[current_lang];break;case"phone registered":alert_msg=alert_dict.register.phone_used[current_lang];break;case"invalid phone":alert_msg=alert_dict.register.inv_phone[current_lang];break;case"invalid password format":alert_msg=alert_dict.register.inv_password[current_lang];break;case"invalid email":alert_msg=alert_dict.register.inv_email[current_lang];break;default:alert_msg=alert_dict.no_reason[current_lang]}App.alert("fail",alert_dict.register.fail[current_lang],alert_msg),failFn&&failFn(response)}))},this.Login=function(upload_data,successFn,failFn){const must_keys=["email","password"];if(!validateUploadData(must_keys,upload_data))return console.error("Login: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));upload_data.application_key=app_key,XHR.api({user_login:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- LOGIN ---------"),App.setUser(data),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: LOGIN (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: LOGIN ---------"),"function"==typeof failFn&&failFn(response)}))},this.SentForgotEmail=function(email,successFn,failFn){if(!email)return console.error('SentForgotEmail: "email" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));let upload_data={email:email,application_key:app_key};XHR.api({user_forget_password:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- FORGOT PASSWORD ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: FORGOT PASSWORD (NULL) ---------"),App.alert("fail",alert_dict.send.fail[current_lang]),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: FORGOT PASSWORD ---------");let err="";switch(data){case"value missing":case"store account not found":err=alert_dict.error_occur[current_lang];break;case"email does not exist":err=alert_dict.forgot_pw.email_not_exist[current_lang];break;case"try again after 1 minutes":err=alert_dict.forgot_pw.try_again_one_min[current_lang];break;default:err=alert_dict.no_reason[current_lang]}App.alert("fail",alert_dict.send.fail[current_lang],err),"function"==typeof failFn&&failFn(response)}))},this.ResetPassword=function(upload_data,successFn,failFn){const must_keys=["id","token","password"];if(!validateUploadData(must_keys,upload_data))return console.error("ResetPassword: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));XHR.api({user_reset_password:JSON.stringify(upload_data)},(function(result,data,response){devlog("--------- RESET PASSWORD ---------"),"function"==typeof successFn&&successFn(data)}),(function(result,data,response){devlog("--------- !!FAIL: RESET PASSWORD ---------");let err="";switch(data){case"value missing":case"store account not found":err=alert_dict.error_occur[current_lang];break;case"invalid password format":err=alert_dict.register.inv_password[current_lang];break;default:err=alert_dict.no_reason[current_lang]}App.alert("fail",alert_dict.resetPw.fail[current_lang],err),"function"==typeof failFn&&failFn(response)}))},this.VerifyResetPasswordToken=function(upload_data,successFn,failFn){const must_keys=["user_id","reset_password_token"];if(!validateUploadData(must_keys,upload_data))return console.error("VerifyResetPasswordToken: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));XHR.api({verify_user_reset_pw_token:JSON.stringify(upload_data)},(function(result,data,response){devlog("--------- VERIFY RESET PASSWORD TOKEN ---------"),"function"==typeof successFn&&successFn(data)}),(function(result,data,response){devlog("--------- !!FAIL: VERIFY RESET PASSWORD TOKEN ---------"),"function"==typeof failFn&&failFn(response)}))},this.UpdatePassword=function(upload_data,successFn,failFn){const must_keys=["id","email","old_password","new_password"];if(!validateUploadData(must_keys,upload_data))return console.error("UpdatePassword: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));upload_data.application_key=app_key,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key},XHR.api({frontend_change_user_password:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- UpdatePassword ---------"),"function"==typeof successFn&&successFn()):(devlog("--------- !!FAIL: UpdatePassword (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UpdatePassword ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetAddressByUserId=function(user_id,successFn,failFn){if(!Validator.dataValid(user_id))return console.error('GetUserAddress: "user_id" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));XHR.api({get_all_delivery_data_excluding_disabled_by_user_id:JSON.stringify({user_id:user_id,application_key:app_key,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}})},(function(result,data,response){Validator.dataValid(data,!0)?(devlog("--------- GET ADDRESS ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- GET ADDRESS (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET ADDRESS ---------"),"function"==typeof failFn&&failFn(response)}))},this.UpdateDelivery=function(upload_data,successFn,failFn){const must_keys=["id"];if(!validateUploadData(must_keys,upload_data))return console.error("UpdateDelivery: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));upload_data.application_key=app_key,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key},XHR.api({update_delivery:JSON.stringify(upload_data)},(function(result,data,response){devlog("--------- UPDATE ADDRESS ---------"),"function"==typeof successFn&&successFn(data)}),(function(result,data,response){devlog("--------- !!FAIL: UPDATE ADDRESS ---------"),"nothing updating"===data?"function"==typeof successFn&&successFn(data):("token verification fail"===data?App.alert("fail",alert_dict.update.fail[current_lang],alert_dict.user_token_expired[current_lang]):App.alert("fail",alert_dict.update.fail[current_lang]),"function"==typeof failFn&&failFn(response))}))},this.NewDelivery=function(upload_data,successFn,failFn){const must_keys=["name","phone","address"];if(!validateUploadData(must_keys,upload_data))return console.error("NewDelivery: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void("function"==typeof failFn&&failFn({data:"user not found"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));upload_data.application_key=app_key,upload_data.user_id=user_data.id,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key},XHR.api({new_delivery:JSON.stringify(upload_data)},(function(result,data,response){devlog("--------- ADD NEW ADDRESS ---------"),"function"==typeof successFn&&successFn(data)}),(function(result,data,response){devlog("--------- !!FAIL: ADD NEW ADDRESS ---------"),"token verification fail"===data?App.alert("fail",alert_dict.update.fail[current_lang],alert_dict.user_token_expired[current_lang]):App.alert("fail",alert_dict.update.fail[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.GetAlfredAddress=function(filter={},successFn,failFn){XHR.api({get_alfred_location_list:JSON.stringify(filter)},(function(result,data,response){if(Validator.dataValid(data,!0)){devlog("--------- GET ALFRED ADDRESS ---------");const list=data.map((function(el){return{code:el.locationId,address:{zh:el.address1||el.locationId,en:el.address1En||el.locationId,cn:el.address1||el.locationId}}}));devlog(list),successFn&&successFn(list)}else devlog("--------- GET ALFRED ADDRESS (NULL) ---------"),failFn&&failFn(response)}),(function(result,data,response){devlog("--------- !!FAIL: GET ALFRED ADDRESS ---------"),failFn&&failFn(response)}))},this.GetSFAddress=function(region="hk",successFn,failFn){let upload_data={};upload_data["filter_"+region]=!0,"en"===current_lang&&(upload_data.lang_en=!0),XHR.api({get_sf_location_list:JSON.stringify(upload_data)},(function(result,data,response){if(Validator.dataValid(data,!0)){devlog("--------- GET SF ADDRESS ---------");const points={business:[],store:[],locker:[],others:[]};eachNode(data,(function(el){let temp=null;temp=1===el.serviceType?points.business:2===el.serviceType?points.store:4===el.serviceType?points.locker:points.others,null!==temp&&temp.push({code:el.serviceCode,address:{zh:el.serviceAddr||el.serviceCode,en:el.serviceAddr||el.serviceCode,cn:el.serviceAddr||el.serviceCode}})})),devlog(points);const list=[];Validator.dataValid(points.business,!0)&&(list.push({code:null,address:{zh:"---------- 營業點 ----------",en:"---------- Business Station ----------",cn:"---------- 营业点 ----------"}}),eachNode(points.business,(function(el){list.push(el)}))),Validator.dataValid(points.store,!0)&&(list.push({code:null,address:{zh:"---------- 順豐站 ----------",en:"---------- SF Store ----------",cn:"---------- 顺丰站 ----------"}}),eachNode(points.store,(function(el){list.push(el)}))),Validator.dataValid(points.locker,!0)&&(list.push({code:null,address:{zh:"---------- 自助櫃 ----------",en:"---------- Locker ----------",cn:"---------- 自助柜 ----------"}}),eachNode(points.locker,(function(el){list.push(el)}))),Validator.dataValid(points.others,!0)&&(list.push({code:null,address:{zh:"---------- 其他 ----------",en:"---------- Others ----------",cn:"---------- 其他 ----------"}}),eachNode(points.others,(function(el){list.push(el)}))),devlog(list),"function"==typeof successFn&&successFn(list)}else devlog("--------- GET SF ADDRESS (NULL) ---------"),"function"==typeof failFn&&failFn(response)}),(function(result,data,response){devlog("--------- !!FAIL: GET SF ADDRESS ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetProductCategories=function(upload_data,successFn,failFn){let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_product_category_data_and_total_number_by_sorting_and_limit_merge_with_order_quantity:JSON.stringify(final_upload_data)},(function(result,data,response){Array.isArray(data)&&Validator.dataValid(data,!0)?(devlog("--------- GET PRODUCT CATEGORY ---------"),"function"==typeof successFn&&successFn(data)):"object"==typeof data&&Validator.dataValid(data.total_number)&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET PRODUCT CATEGORY ---------"),"function"==typeof successFn&&successFn(data.item_list)):(devlog("--------- !!FAIL: GET PRODUCT CATEGORY (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET PRODUCT CATEGORY ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetProductByFilter=function(upload_data,successFn,failFn){let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_product_data_and_total_number_by_sorting_and_limit_merge_with_order_quantity:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET PRODUCT BY FILTER ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET PRODUCT BY FILTER (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET PRODUCT BY FILTER ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetProductByIdList=function(product_id_list,successFn,failFn){Validator.dataValid(product_id_list,!0)?XHR.api({get_all_data_excluding_disabled_by_data_type_and_id_list:JSON.stringify({application_key:app_key,id_list:product_id_list,data_type:"product_data"})},(function(result,data,response){Validator.dataValid(data,!0)?(devlog("--------- GET PRODUCT BY ID LIST ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET PRODUCT BY ID LIST (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET PRODUCT BY ID LIST ---------"),"function"==typeof failFn&&failFn(response)})):"function"==typeof failFn&&failFn(null)},this.GetProductExcludingAdditionByProductCodeList=function(product_code_list,successFn,failFn){Validator.dataValid(product_code_list,!0)?XHR.api({get_all_product_data_excluding_disabled_and_additional_product_by_product_code_list_and_application_key:JSON.stringify({application_key:app_key,product_code_list:product_code_list})},(function(result,data,response){Validator.dataValid(data,!0)?(devlog("--------- GET PRODUCT BY CODE LIST ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET PRODUCT BY CODE LIST (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET PRODUCT BY CODE LIST ---------"),"function"==typeof failFn&&failFn(response)})):"function"==typeof failFn&&failFn(null)},this.GetProductByParams=function(upload_data,successFn,failFn){if(!upload_data||!upload_data.code&&!upload_data.meta_url)return console.error('GetProductByParams: "meta_url/code" is missing'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));let final_upload_data={application_key:app_key};upload_data.meta_url?final_upload_data.meta_url=upload_data.meta_url:upload_data.code&&(final_upload_data.code=upload_data.code);for(const key in upload_data)"code"!==key&&"meta_url"!==key&&(final_upload_data[key]=upload_data[key]);XHR.api({frontend_search_product_by_params:JSON.stringify(final_upload_data)},(function(result,data,response){if(Validator.dataValid(data))if(Validator.dataValid(final_upload_data.code)&&Validator.dataValid(final_upload_data.id))if(data&&"object"==typeof data&&Object.keys(data).length>0){devlog("--------- GET PRODUCT BY PARAMS : Additional Product ---------");const return_data={product_data:data};devlog(return_data),"function"==typeof successFn&&successFn(return_data)}else devlog("--------- !!FAIL: GET PRODUCT BY PARAMS (NULL) : Additional Product ---------"),"function"==typeof failFn&&failFn(response);else if(Validator.dataValid(data.product_list,!0)){devlog("--------- GET PRODUCT BY PARAMS ---------");let return_data={};!0===data.product_list[0].additional_product?return_data.product_data=data.product_list[0]:(return_data.product_list=data.product_list,Validator.dataValid(data.additional_product_list,!0)&&(return_data.additional_product_list=data.additional_product_list)),devlog(return_data),"function"==typeof successFn&&successFn(return_data)}else devlog("--------- !!FAIL: GET PRODUCT BY PARAMS (NULL) ---------"),"function"==typeof failFn&&failFn(response);else devlog("--------- !!FAIL: GET PRODUCT BY PARAMS (NULL) ---------"),"function"==typeof failFn&&failFn(response)}),(function(result,data,response){devlog("--------- !!FAIL: GET PRODUCT BY PARAMS ---------"),"function"==typeof failFn&&failFn(response)}))},this.SearchProduct=function(upload_data,successFn,failFn){const must_keys=["key_word"];if(!validateUploadData(must_keys,upload_data))return console.error("SearchProduct: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));let final_upload_data={key_word:"",sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key};for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({search_product_by_limit_and_page:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- SEARCH PRODUCT ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: SEARCH PRODUCT (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: SEARCH PRODUCT ---------"),"function"==typeof failFn&&failFn(response)}))},this.CalculateOrderAmount=function(upload_data,successFn,failFn){const must_keys=["product_data_list","discount_type","cash_dollar","coupon_code","delivery_method","payment_method"];if(!validateUploadData(must_keys,upload_data))return console.error("CalculateOrderAmount: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));let final_upload_data={store_account_data:store_account_data,application_key:app_key,user_data:user_data||[],user_id:user_data?user_data.id:null,product_data_list:[],discount_type:upload_data.discount_type,cash_dollar:upload_data.cash_dollar,coupon_code:upload_data.coupon_code,delivery_method:upload_data.delivery_method,payment_method:upload_data.payment_method};const product_data_list=upload_data.product_data_list.map((function(item){return{product_id:item.product_id,quantity:item.quantity,amount:item.amount}}));final_upload_data.product_data_list=product_data_list,XHR.api({calculate_order_amount:JSON.stringify(final_upload_data)},(function(result,data,response){data?(devlog("--------- CALCULATE ORDER TOTAL ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: CALCULATE ORDER TOTAL (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: CALCULATE ORDER TOTAL ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetOrderStripeData=function(upload_data,successFn,failFn){const must_keys=["product_data_list","discount_type","cash_dollar","coupon_code","delivery_method","payment_method"];if(!validateUploadData(must_keys,upload_data))return console.error("GetStripeKey: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));if(!user_data&&!upload_data.guest_email)return App.alert("fail",alert_dict.login.requiredOrGuest[current_lang]),void("function"==typeof failFn&&failFn({data:"user not found"}));const local_user=App.localStorage.get("user_data");if(!(upload_data.guest_email||local_user&&local_user.token))return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));let final_upload_data={store_account_data:store_account_data,application_key:app_key,user_data:user_data||[],user_id:user_data?user_data.id:null,product_data_list:[],discount_type:upload_data.discount_type,cash_dollar:upload_data.cash_dollar,coupon_code:upload_data.coupon_code,delivery_method:upload_data.delivery_method,payment_method:upload_data.payment_method};const product_data_list=upload_data.product_data_list.map((function(item){return{product_id:item.product_id,quantity:item.quantity,amount:item.amount}}));final_upload_data.product_data_list=product_data_list,user_data&&(final_upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key}),XHR.api({get_order_stripe_payment_data:JSON.stringify(final_upload_data)},(function(result,data,response){data?(devlog("--------- GET STRIPE DATA ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET STRIPE DATA (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET STRIPE DATA ---------"),"token verification fail"===data?App.alert("fail",alert_dict.user_token_expired[current_lang]):App.alert("fail",alert_dict.payment.no_stripe_data[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.GetOrderData=function(upload_data,successFn,failFn){const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_order_data_and_total_number_by_sorting_and_limit:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET ORDER DATA ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET ORDER DATA (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET ORDER DATA ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetOrderById=function(order_id,successFn,failFn){if(!Validator.dataValid(order_id))return console.error('"order_id" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));XHR.api({get_order_data_by_application_key_and_id:JSON.stringify({id:order_id,application_key:app_key,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}})},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- GET ORDER BY ID ---------"),"function"==typeof failFn&&successFn(data)):(devlog("--------- !!FAIL: GET ORDER BY ID (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET ORDER BY ID ---------"),"token verification fail"===data&&App.alert("fail",alert_dict.user_token_expired[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.UpdateOrder=function(upload_data,successFn,failFn){const must_keys=["id"];if(!validateUploadData(must_keys,upload_data))return console.error("UpdateOrder: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));upload_data.application_key=app_key,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key},XHR.api({update_order:JSON.stringify(upload_data)},(function(result,data,response){data?(devlog("--------- UPDATE ORDER ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: UPDATE ORDER (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UPDATE ORDER ---------"),"token verification fail"===data&&App.alert("fail",alert_dict.user_token_expired[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.UploadBankTransferImg=function(upload_data,successFn,failFn){const must_keys=["order_id","img_base64"];if(!validateUploadData(must_keys,upload_data))return console.error('UploadBankTransferImg: "order_id"/"img_base64" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!(upload_data.guest_email||local_user&&local_user.token))return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));let final_upload_data=JSON.parse(JSON.stringify(upload_data));final_upload_data.application_key=app_key,user_data&&(final_upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key}),final_upload_data.guest_email&&delete final_upload_data.guest_email,XHR.api({upload_bank_transfer_image_to_order:JSON.stringify(final_upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- UPLOAD BANK TRANSFER IMAGE ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: UPLOAD BANK TRANSFER IMAGE (NULL) ---------"),App.alert("fail",alert_dict.upload.fail[current_lang],alert_dict.no_reason[current_lang]),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UPLOAD BANK TRANSFER IMAGE ---------");let alert_msg="";switch(data){case"order not found":alert_msg=alert_dict.upload.order_not_found[current_lang];break;case"payment method is not bank transfer":alert_msg=alert_dict.upload.not_bank_transfer[current_lang];break;case"token verification fail":alert_msg=alert_dict.user_token_expired[current_lang];break;default:alert_msg=alert_dict.error_occur[current_lang]+": "+JSON.stringify(data)}App.alert("fail",alert_dict.upload.fail[current_lang],alert_msg),"function"==typeof failFn&&failFn(response)}))},this.Checkout=function(upload_data,successFn,failFn){const must_keys=["product_data_list","sub_total_amount","cash_dollar","coupon_data","discount_type","discount_amount","delivery_data","delivery_amount","payment_gateway_amount","total_amount","remark","payment_data"];if(!validateUploadData(must_keys,upload_data))return console.error("Checkout: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));if(!user_data&&!upload_data.guest_email)return App.alert("fail",alert_dict.login.requiredOrGuest[current_lang]),void("function"==typeof failFn&&failFn({data:"user not found"}));const local_user=App.localStorage.get("user_data");if(!(upload_data.guest_email||local_user&&local_user.token))return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));let temp_product_data_list;user_data?(upload_data.user_id=user_data.id,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key}):upload_data.user_id=null,upload_data.application_key=app_key;const product_data_list=JSON.parse(JSON.stringify(upload_data.product_data_list)).map((function(item){return{product_id:item.product_id,quantity:item.quantity,amount:item.amount}}));upload_data.product_data_list=product_data_list,XHR.api({check_out:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- CHECKOUT ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: CHECKOUT (NULL) ---------"),!upload_data.payment_data||"stripe"!==upload_data.payment_data.payment_method&&"paypal"!==upload_data.payment_data.payment_method?App.alert("fail",alert_dict.payment.fail[current_lang],alert_dict.payment.payment_data_err[current_lang]):App.alert("fail",alert_dict.payment.fail[current_lang],alert_dict.payment.stripe_data_err[current_lang]),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: CHECKOUT ---------");let error_msg="";switch(data){case"value missing":case"application key is required":case"missing payment data":error_msg=alert_dict.payment.payment_data_err[current_lang];break;case"no product found":case"no product":error_msg=alert_dict.payment.no_data[current_lang];break;case"only one discount type can be used":error_msg=alert_dict.payment.inv_multiple_coupon[current_lang];break;case"user not found":case"user is disabled":error_msg=alert_dict.user.not_found[current_lang];break;case"stripe key missing":error_msg=alert_dict.payment.strip_error[current_lang];break;case"paypal is not supported yet":error_msg=alert_dict.payment.paypal_error[current_lang];break;case"coupon not found":error_msg=alert_dict.coupon.not_found[current_lang];break;case"coupon is used":error_msg=alert_dict.coupon.used[current_lang];break;case"coupon is disabled":case"coupon is expired":error_msg=alert_dict.coupon.disabled[current_lang];break;case"please login to apply coupon":error_msg=alert_dict.coupon.no_login[current_lang];break;case"user is not allow to use this coupon":error_msg=alert_dict.coupon.inv_user[current_lang];break;case"coupon is not started to use":error_msg=alert_dict.coupon.not_start[current_lang];break;case"not enough inventory":error_msg=alert_dict.payment.not_enough_stock[current_lang];break;case"payment fail":case"stripe payment fail":error_msg=alert_dict.payment.stripe_data_err[current_lang];break;case"missing delivery data":case"invalid delivery method":case"invalid delivery phone":error_msg=alert_dict.payment.delivery_err[current_lang];break;case"token verification fail":error_msg=alert_dict.user_token_expired[current_lang];break;default:error_msg=alert_dict.error_occur[current_lang]+"("+JSON.stringify(data)+")"}App.alert("fail",alert_dict.payment.fail[current_lang],error_msg),"function"==typeof failFn&&failFn(response)}))},this.GetCouponByUserId=function(user_id,successFn,failFn,current_subtotal=-1){if(!Validator.dataValid(user_id))return console.error('"user_id" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));let payload={user_id:user_id,application_key:app_key,filter_expiry:!0,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}};current_subtotal>-1&&(payload.current_subtotal=current_subtotal),XHR.api({get_all_public_and_private_coupon_data_excluding_disabled_and_not_usable_by_application_key_and_user_id:JSON.stringify(payload)},(function(result,data,response){Validator.dataValid(data,!0)?(devlog("--------- GET COUPON DATA BY USER ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET COUPON DATA BY USER (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET COUPON DATA BY USER ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetCouponByCode=function(code,successFn,failFn){if(!Validator.dataValid(code))return console.error('"code" is required'),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));XHR.api({get_coupon_data_excluding_disabled_by_application_key_and_code:JSON.stringify({application_key:app_key,code:code,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}})},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- GET COUPON DATA BY CODE ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET COUPON DATA BY CODE (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET COUPON DATA BY CODE ---------"),"function"==typeof failFn&&failFn(response)}))},this.PreOrder=function(upload_data,successFn,failFn){const must_keys=["product_id","book_amount"];if(!validateUploadData(must_keys,upload_data))return console.error("PreOrder: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void("function"==typeof failFn&&failFn({data:"user not found"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));upload_data.user_id=user_data.id,upload_data.application_key=app_key,upload_data.validate_token={token:local_user.token,user_id:local_user.id,application_key:app_key},XHR.api({add_product_booking:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- PREORDER ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: PREORDER (NULL) ---------"),App.alert("fail",alert_dict.product.preorder.fail[current_lang]),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: PREORDER ---------");let error_msg="";switch(data){case"no purchased plan":case"module not found":error_msg=alert_dict.product.preorder.not_available[current_lang];break;case"book amount cannot smaller than or equals 0":error_msg=alert_dict.product.preorder.at_least_one_item[current_lang];break;case"user not found":error_msg=alert_dict.user.not_found[current_lang];break;case"product not found":error_msg=alert_dict.product.not_found[current_lang];break;case"token verification fail":error_msg=alert_dict.user_token_expired[current_lang];break;default:error_msg=alert_dict.error_occur[current_lang]+"("+JSON.stringify(data)+")"}App.alert("fail",alert_dict.product.preorder.fail[current_lang],error_msg),"function"==typeof failFn&&failFn(response)}))},this.GetPreOrderData=function(upload_data,successFn,failFn){const must_keys=["user_id"];if(!validateUploadData(must_keys,upload_data))return console.error("GetPreOrderData: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void("function"==typeof failFn&&failFn({data:"value missing"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key,validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_product_booking_data_by_sorting_limit:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET PRE-ORDER DATA ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: GET PRE-ORDER DATA (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET PRE-ORDER DATA ---------"),"function"==typeof failFn&&failFn(response)}))},this.GetFavoriteProductsOfUser=function(successFn,failFn){user_data?this.GetUserDataById(user_data.id,(function(user){Validator.dataValid(user.product_like_list,!0)?(devlog("--------- GET FAVORITES ---------"),"function"==typeof successFn&&successFn(user.product_like_list)):(devlog("--------- !!FAIL: GET FAVORITES (NULL) ---------"),"function"==typeof failFn&&failFn([]))}),(function(){devlog("--------- !!FAIL: GET FAVORITES ---------"),"function"==typeof failFn&&failFn([])}),!0):"function"==typeof failFn&&failFn([])},this.AddToFavorite=function(product_code,successFn,failFn){if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void("function"==typeof failFn&&failFn({data:"user not found"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));const upload_data={user_id:user_data.id,application_key:app_key,product_code:product_code,action_type:"add",validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}};XHR.api({update_product_like_list:JSON.stringify(upload_data)},(function(result,data,response){data?(devlog("--------- ADD PRODUCT TO FAVORITE ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: ADD PRODUCT TO FAVORITE (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: ADD PRODUCT TO FAVORITE ---------"),"token verification fail"===data?App.alert("fail",alert_dict.update.fail[current_lang],alert_dict.user_token_expired[current_lang]):App.alert("fail",alert_dict.update.fail[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.RemoveFromFavorite=function(product_code,successFn,failFn){if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void("function"==typeof failFn&&failFn({data:"user not found"}));const local_user=App.localStorage.get("user_data");if(!local_user||!local_user.token)return App.alert("fail",alert_dict.user_token_expired[current_lang]),void("function"==typeof failFn&&failFn({data:"token verification fail"}));const upload_data={user_id:user_data.id,application_key:app_key,product_code:product_code,action_type:"remove",validate_token:{token:local_user.token,user_id:local_user.id,application_key:app_key}};XHR.api({update_product_like_list:JSON.stringify(upload_data)},(function(result,data,response){data?(devlog("--------- REMOVE PRODUCT FROM FAVORITE ---------"),"function"==typeof successFn&&successFn(data)):(devlog("--------- !!FAIL: REMOVE PRODUCT FROM FAVORITE (NULL) ---------"),"function"==typeof failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: REMOVE PRODUCT FROM FAVORITE ---------"),"token verification fail"===data?App.alert("fail",alert_dict.user_token_expired[current_lang]):App.alert("fail",alert_dict.update.fail[current_lang]),"function"==typeof failFn&&failFn(response)}))},this.GetAppointmentSetting=function(successFn,failFn){XHR.api({get_all_data_by_data_type_and_application_key:JSON.stringify({application_key:app_key,data_type:"appointment_setting_data"})},(function(result,data,response){if(Validator.dataValid(data,!0)){const valid_data=data.filter((function(e){return!e.disabled}));Validator.dataValid(valid_data,!0)?(devlog("--------- GET APPOINTMENT SETTING ---------"),"function"==typeof successFn&&successFn(valid_data)):(devlog("--------- !!FAIL: GET APPOINTMENT SETTING (NULL) ---------"),"function"==typeof failFn&&failFn(response))}else devlog("--------- !!FAIL: GET APPOINTMENT SETTING (NULL) ---------"),"function"==typeof failFn&&failFn(response)}),(function(result,data,response){devlog("--------- !!FAIL: GET APPOINTMENT SETTING ---------"),"function"==typeof failFn&&failFn(response)}))},this.MakeAppointment=function(upload_data,successFn,failFn){const must_keys=["date","start_time","end_time","appointment_id"];if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void(failFn&&failFn(null));if(!validateUploadData(must_keys,upload_data))return console.error("MakeAppointment: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));let final_upload_data={application_key:app_key,user_id:user_data.id,shop:-1,remark:""};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({add_appointment_record:JSON.stringify(final_upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- MAKE APPOINTMENT ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: MAKE APPOINTMENT (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: MAKE APPOINTMENT ---------");let alert_msg="";switch(response.data){case"data not found":alert_msg=alert_dict.appointment.no_data[current_lang];break;case"user not found":case"user is disabled":alert_msg=alert_dict.user.not_found[current_lang];break;default:alert_msg=alert_dict.error_occur[current_lang]+": "+JSON.stringify(response.data)}App.alert("fail",alert_dict.appointment.fail[current_lang],alert_msg),failFn&&failFn(response)}))},this.CancelAppointment=function(appointment_id,successFn,failFn){if(!Validator.dataValid(appointment_id))return console.error("CancelAppointment: missing appointment id"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));XHR.api({update_appointment:JSON.stringify({id:appointment_id,status:"cancelled"})},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- CANCEL APPOINTMENT ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: CANCEL APPOINTMENT (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: CANCEL APPOINTMENT ---------"),"nothing updating"===data?successFn&&successFn(data):failFn&&failFn(response)}))},this.UpdateAppointment=function(upload_data,successFn,failFn){const must_keys=["id"];if(!validateUploadData(must_keys,upload_data))return console.error("UpdateAppointment: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));upload_data.application_key=app_key,XHR.api({update_appointment:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- UPDATE APPOINTMENT ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: UPDATE APPOINTMENT (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UPDATE APPOINTMENT ---------"),"nothing updating"===data?successFn&&successFn(data):failFn&&failFn(response)}))},this.GetAppointmentRecords=function(upload_data,successFn,failFn){let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_raw_appointment_record_data_and_total_number_by_sorting_and_limit:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET APPOINTMENT DATA ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: GET APPOINTMENT DATA (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET APPOINTMENT DATA ---------"),failFn&&failFn(response)}))},this.GetRentingSetting=function(successFn,failFn){XHR.api({get_renting_product_by_application_key:JSON.stringify({application_key:app_key})},(function(result,data,response){if(data&&Validator.dataValid(data.item_list,!0)){const valid_data=data.item_list.filter((function(e){return!e.disabled}));Validator.dataValid(valid_data,!0)?(devlog("--------- GET RENTING SETTING ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: GET RENTING SETTING (NULL) ---------"),failFn&&failFn(response))}else devlog("--------- !!FAIL: GET RENTING SETTING (NULL) ---------"),failFn&&failFn(response)}),(function(result,data,response){devlog("--------- !!FAIL: GET RENTING SETTING ---------"),failFn&&failFn(response)}))},this.NewRenting=function(upload_data,successFn,failFn){const must_keys=["start_date","end_date","renting_product_id"];if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void(failFn&&failFn(null));if(!validateUploadData(must_keys,upload_data))return console.error("NewRenting: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));let final_upload_data={application_key:app_key,user_id:user_data.id,remark:""};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({new_renting_record:JSON.stringify(final_upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- RENTING ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: RENTING (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: RENTING ---------");let alert_msg="";switch(response.data){case"renting product not found":case"renting product is disabled":alert_msg=alert_dict.renting.no_data[current_lang];break;case"start date cannot smaller than end date":alert_msg=alert_dict.renting.inv_end_date[current_lang];break;case"user not found":case"user is disabled":alert_msg=alert_dict.user.not_found[current_lang];break;default:alert_msg=alert_dict.error_occur[current_lang]+": "+JSON.stringify(response.data)}App.alert("fail",alert_dict.renting.fail[current_lang],alert_msg),failFn&&failFn(response)}))},this.GetRentingRecords=function(upload_data,successFn,failFn){let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_renting_record_by_application_key:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET RENTING RECORD ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: GET RENTING RECORD (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET RENTING RECORD ---------"),failFn&&failFn(response)}))},this.UpdateRenting=function(upload_data,successFn,failFn){const must_keys=["id"];if(!validateUploadData(must_keys,upload_data))return console.error("UpdateAppointment: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));upload_data.application_key=app_key,XHR.api({update_renting_record:JSON.stringify(upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- UPDATE RENTING ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: UPDATE RENTING (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: UPDATE RENTING ---------"),"nothing updating"===data?successFn&&successFn(data):failFn&&failFn(response)}))},this.CancelRenting=function(rent_id,successFn,failFn){if(!Validator.dataValid(rent_id))return console.error("CancelRenting: missing renting id"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));XHR.api({update_renting_record:JSON.stringify({id:rent_id,status:"cancelled"})},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- CANCEL RENTING ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: CANCEL RENTING (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: CANCEL RENTING ---------"),"nothing updating"===data?successFn&&successFn(data):failFn&&failFn(response)}))},this.NewQuotation=function(upload_data,successFn,failFn){const must_keys=["service_type_id","service_size","service_quantity","file_path","single_price","total"];if(!user_data)return App.alert("fail",alert_dict.user.not_found[current_lang]),void(failFn&&failFn(null));if(!validateUploadData(must_keys,upload_data))return console.error("NewQuotation: value missing"),App.alert("fail",alert_dict.error_occur[current_lang]),void(failFn&&failFn({data:"value missing"}));let final_upload_data={application_key:app_key,user_id:user_data.id,remark:"",quotation_status:"approved"};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({new_quotation:JSON.stringify(final_upload_data)},(function(result,data,response){Validator.dataValid(data)?(devlog("--------- QUOTATION ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: QUOTATION (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: QUOTATION ---------"),App.alert("fail",alert_dict.quotation.fail[current_lang],""),failFn&&failFn(response)}))},this.GetQuotation=function(upload_data,successFn,failFn){let final_upload_data={sorting:"create_date",direction:"DESC",limit:999,page:1,application_key:app_key};if(Validator.dataValid(upload_data))for(const key in upload_data)final_upload_data[key]=upload_data[key];XHR.api({get_quotation_data_and_total_by_sorting_and_limit:JSON.stringify(final_upload_data)},(function(result,data,response){data&&Validator.dataValid(data.item_list,!0)?(devlog("--------- GET QUOTATION RECORD ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: GET QUOTATION RECORD (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET QUOTATION RECORD ---------"),failFn&&failFn(response)}))},this.GetQuotationCategories=function(successFn,failFn){const payload={application_key:app_key,data_type:"product_category_data",include_pos:!0};XHR.api({get_all_data_by_data_type_and_application_key:JSON.stringify(payload)},(function(result,data,response){Validator.dataValid(data,!0)?(devlog("--------- GET QUOTATION CATEGORIES ---------"),successFn&&successFn(data)):(devlog("--------- !!FAIL: GET QUOTATION CATEGORIES (NULL) ---------"),failFn&&failFn(response))}),(function(result,data,response){devlog("--------- !!FAIL: GET QUOTATION CATEGORIES ---------"),failFn&&failFn(response)}))}},window.renderAppointmentDates=function(appointment){let enableDate_list=[],enableWeekDay_list=[];appointment&&Validator.dataValid(appointment.generate_rules,!0)&&eachNode(appointment.generate_rules,(function(rule){if("specific_date"===rule.select_type)enableDate_list.push(rule.select_value);else if("everyday"===rule.select_type)enableDate_list=null,enableWeekDay_list=null;else switch(rule.select_type){case"mon":enableWeekDay_list.push(1);break;case"tue":enableWeekDay_list.push(2);break;case"wed":enableWeekDay_list.push(3);break;case"thu":enableWeekDay_list.push(4);break;case"fri":enableWeekDay_list.push(5);break;case"sat":enableWeekDay_list.push(6);break;case"sun":enableWeekDay_list.push(0)}})),calendarPicker&&calendarPicker.set({enableWeekDay_list:enableWeekDay_list,enableDate_list:enableDate_list},!0,!0)},window.getAppointmentTimeList=function(appointment,selected_date){let this_time_list=[];if(dq("#select-appointment-time")&&AppUI.clearNodes(dq("#select-appointment-time")),appointment&&Validator.dataValid(appointment.generate_rules,!0)&&selected_date)if(eachNode(appointment.generate_rules,(function(item){let isRelatedRule=!1;if("specific_date"===item.select_type&&selected_date===item.select_value&&(isRelatedRule=!0),!1===isRelatedRule){const check_date=DateFormatter.convertStrToDate(selected_date);if(check_date){const check_day=check_date.getDay();switch(item.select_type){case"mon":1===check_day&&(isRelatedRule=!0);break;case"tue":2===check_day&&(isRelatedRule=!0);break;case"wed":3===check_day&&(isRelatedRule=!0);break;case"thu":4===check_day&&(isRelatedRule=!0);break;case"fri":5===check_day&&(isRelatedRule=!0);break;case"sat":6===check_day&&(isRelatedRule=!0);break;case"sun":0!==check_day&&7!==check_day||(isRelatedRule=!0)}}}if(!1===isRelatedRule&&"everyday"===item.select_type&&(isRelatedRule=!0),!0===isRelatedRule){const start_time_parts=item.start_time.split(":"),end_time_parts=item.end_time.split(":");let start_time=new Date("2023-01-01");start_time.setHours(parseInt(start_time_parts[0]),parseInt(start_time_parts[1]),0);let end_time=new Date("2023-01-01");end_time.setHours(parseInt(end_time_parts[0]),parseInt(end_time_parts[1]),0);const diff=Math.floor((end_time.getTime()-start_time.getTime())/6e4),slots=Math.floor(diff/item.time_split);for(let i=0;iinput")&&eachNode(dqa(".qty-setter .qty-input>input"),(function(e){e.addEventListener("keydown",(function(ev){if(ev.defaultPrevented)return;let handled=!1;void 0!==ev.keyCode&&(Validator.isNumberInput(ev.keyCode)||Validator.isFunctionKey(ev.keyCode)?(Validator.isNumberInput(ev.keyCode)||Validator.isFunctionKey(ev.keyCode))&&(handled=!1):handled=!0),handled&&(ev.preventDefault(),e.value=Formatter.numbersOnlyString(e.value))}),!0)})),dq(".btn-logout")&&eachNode(dqa(".btn-logout"),(function(e){e.addEventListener("click",(function(){App.logout()}))})),dq("#btn-submit-foot-subscribe")&&dq("#foot-subscribe-email")&&(dq("#btn-submit-foot-subscribe").addEventListener("click",(function(){cutClass(dq("#foot-subscribe"),["error"]),dq("#foot-subscribe-email").value&&Validator.regexEmail(dq("#foot-subscribe-email").value)?(App.alert("success",alert_dict.subscribe.success[current_lang]),cutClass(dq("#foot-subscribe"),["error"]),dq("#foot-subscribe-email").value=""):addClass(dq("#foot-subscribe"),["error"])})),dq("#foot-subscribe-email").addEventListener("input",(function(){cutClass(dq("#foot-subscribe"),["error"])})))})),window.addEventListener("resize",(function(){AppUI.vhCSS()})),window.addEventListener("load",(function(){AppUI.vhCSS()}));