{"version":3,"file":"productPurchase.js","mappings":";;;;AAAA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,UAAU,GAAG,YAAY;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA,8CAA8C,UAAU;AACxD;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA,mCAAmC,YAAY;AAC/C,8CAA8C,UAAU;AACxD;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mDAAmD,SAAS;AAC5D;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,oCAAoC,OAAO;AAC3C;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,WAAW;AACX;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,EAAE;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA,WAAW;AACX;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qEAAqE;AACrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,gBAAgB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,QAAQ;AACR;AACA;AACA,sCAAsC,oCAAoC;AAC1E;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sEAAsE,IAAI,KAAK,IAAI,KAAK,IAAI;AAC5F;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,oEAAoE,IAAI,KAAK,IAAI;AACjF;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,oEAAoE,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AACnG;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,qEAAqE,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AAC7G;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,4EAA4E,IAAI,KAAK,IAAI,KAAK,IAAI;AAClG;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;;ACjfmD;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,iBAAiB;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,YAAY,WAAW;AACvB,IAAI,QAAQ;AACZ,IAAI,QAAQ;AACZ,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA,YAAY,OAAO;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,MAAM;AACN;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,YAAY,UAAU;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP,GAAG;AACH;AACA;AACA,iDAAe,UAAU,EAAC;;;ACpHoB;AACE;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,0BAA0B,kBAAkB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA,YAAY;AACZ;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,qBAAqB,iBAAiB;AACtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+DAA+D;AAC/D,gEAAgE;AAChE,WAAW;AACX;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,8DAA8D;AAC9D,6DAA6D;AAC7D,SAAS;AACT;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,UAAU,UAAU;AACpB;AACA,QAAQ;AACR;AACA,UAAU,UAAU;AACpB;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN,2CAA2C,QAAQ;AACnD;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,UAAU,UAAU;AACpB,UAAU;AACV;AACA;AACA,WAAW;AACX;AACA,QAAQ;AACR;AACA,UAAU,UAAU;AACpB,UAAU;AACV;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA,4CAAe,KAAK,EAAC;;;AC7TrB;AACA;AACuC;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wDAAwD,UAAU;AAClE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,aAAa;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAoC,MAAM;AAC1C;AACA;AACA;AACA;AACA;AACA,kBAAkB,MAAM;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB;AACnB;AACA,kBAAkB;AAClB;AACA;AACA;AACA,mBAAmB;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA,yEAAyE,MAAM,kBAAkB,MAAM;AACvG;AACA;AACA;AACA;AACA,+CAA+C,MAAM;AACrD;AACA;AACA,aAAa;AACb;AACA;AACA,OAAO;AACP;AACA,GAAG;AACH;AACA;AACA;AACA;AACA,wDAAwD,UAAU;AAClE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB,yBAAyB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2DAA2D,UAAU,oBAAoB;AACzF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA,UAAU;AACV;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mDAAmD,SAAS;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,4DAA4D,UAAU;AACtE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0BAA0B;AAC1B;AACA,+CAA+C;AAC/C,+CAA+C;AAC/C,+CAA+C;AAC/C;AACA;AACA;AACA,4BAA4B,oCAAoC;AAChE;AACA;AACA,uEAAuE,UAAU;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf,cAAc;AACd;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA,YAAY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT,OAAO;AACP,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA,YAAY,YAAY;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA,8BAA8B,KAAK;AACnC;AACA;AACA;AACA,UAAU,KAAK;AACf,UAAU;AACV;AACA,UAAU,KAAK;AACf;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA,YAAY,wGAAwG;AACpH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD,GAAG;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gDAAgD,GAAG;AACnD;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAgB;AACtB,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,cAAc,iDAAiD;AAC/D;AACA;AACA;AACA,kFAAkF,GAAG;AACrF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,OAAO;AACP,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA,YAAY,iBAAiB;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA,uEAAuE,GAAG;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA,YAAY,iCAAiC;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,YAAY,4CAA4C;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;AACA;AACA,OAAO;AACP;AACA,MAAM;AACN;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA,YAAY,mBAAmB;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,4CAA4C;AACxD;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA,OAAO;AACP,GAAG;AACH;AACA;AACA","sources":["webpack://build/../ilcasalingo/assets/javascripts/components/utilities.js","webpack://build/../ilcasalingo/assets/javascripts/common/cartDrawer.js","webpack://build/../ilcasalingo/assets/javascripts/components/store.js","webpack://build/../ilcasalingo/assets/javascripts/productPurchase.js"],"sourcesContent":["// ===============================================================\r\n// ADIÇÃO MANUAL DE ASSET\r\n// ===============================================================\r\n// Usado para incluir assets no código de forma manual, conforme a necessidade\r\nexport function addAsset(source, onloadCallback) {\r\n if (!source || source === '') return console.error(`addAsset: caminho não definido.`);\r\n\r\n if (source.includes('.js')) {\r\n const scriptTag = document.createElement('script');\r\n scriptTag.setAttribute('src', source);\r\n\r\n if (onloadCallback && typeof onloadCallback === 'function') {\r\n scriptTag.onload = onloadCallback;\r\n }\r\n\r\n return document.body.appendChild(scriptTag);\r\n } else if (source.includes('.css')) {\r\n const linkTag = document.createElement('link');\r\n linkTag.setAttribute('rel', 'stylesheet');\r\n linkTag.setAttribute('type', 'text/css');\r\n linkTag.setAttribute('href', source);\r\n return document.head.appendChild(linkTag);\r\n } else {\r\n const error = `addAsset: Erro ao criar o asset. Tipo de script não definido, ou não possui tratamento para este tipo de asset.`;\r\n return console.error(error, source);\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// BUSCA O CARRINHO ATIVO\r\n// ===============================================================\r\nexport async function getCart() {\r\n try {\r\n const response = await fetch('/carrinho', {\r\n headers: {\r\n Accept: 'application/json',\r\n },\r\n });\r\n\r\n return await response.json();\r\n } catch (error) {\r\n console.error('Erro ao buscar os dados do carrinho');\r\n console.error(error);\r\n return false;\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// SERIALIZE ARRAY\r\n// ===============================================================\r\nexport function serializeArray(form) {\r\n const formData = new FormData(form);\r\n const data = {};\r\n\r\n for (const [name, value] of formData) {\r\n data[name] = value;\r\n }\r\n\r\n const formBody = [];\r\n\r\n for (const key in data) {\r\n const encodeKey = encodeURIComponent(key);\r\n const encodeValue = encodeURIComponent(data[key]);\r\n formBody.push(`${encodeKey}=${encodeValue}`);\r\n }\r\n\r\n return formBody.join('&');\r\n}\r\n\r\n// ===============================================================\r\n// URL ENCODE FORM DATA\r\n// ===============================================================\r\nexport function urlencodeFormData(formData) {\r\n let string = '';\r\n\r\n function encode(s) {\r\n return encodeURIComponent(s).replace(/%20/g, '+');\r\n }\r\n\r\n for (const pair of formData.entries()) {\r\n if (typeof pair[1] == 'string') {\r\n string += (string ? '&' : '') + encode(pair[0]) + '=' + encode(pair[1]);\r\n }\r\n }\r\n return string;\r\n}\r\n\r\n// ===============================================================\r\n// SLIDE TOGGLE\r\n// ===============================================================\r\nexport function slideToggle(contentWrapper, content, duration = 500) {\r\n let initialHeight = window.getComputedStyle(contentWrapper).height;\r\n\r\n if (initialHeight == '0px') {\r\n return slideDown(contentWrapper, content, duration);\r\n } else {\r\n return slideUp(contentWrapper, duration);\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// SLIDE UP\r\n// ===============================================================\r\nexport function slideUp(contentWrapper, duration = 500) {\r\n contentWrapper.style.height = '0px';\r\n contentWrapper.style.transition = `height ${duration} ease`;\r\n}\r\n\r\n// ===============================================================\r\n// SLIDE DOWN\r\n// ===============================================================\r\nexport function slideDown(contentWrapper, content, duration = 500) {\r\n let innerHeight = content.clientHeight;\r\n\r\n contentWrapper.style.height = `${innerHeight}px`;\r\n contentWrapper.style.transition = `height ${duration} ease`;\r\n}\r\n\r\n// ===============================================================\r\n// UPDATE DISCOUNT IN PRODUCT BLOCK\r\n// ===============================================================\r\nexport function updatePriceBlock() {\r\n const priceEls = document.querySelectorAll('[data-init-price]');\r\n\r\n if (priceEls == null) return;\r\n\r\n priceEls.forEach((priceEl) => {\r\n const discount = priceEl.dataset.discountPercent;\r\n\r\n priceEl.dispatchEvent(new Event('change'));\r\n\r\n // discount\r\n if (discount != '0') {\r\n priceEl.style.setProperty('--discount', `'-${discount}%'`);\r\n }\r\n });\r\n}\r\n\r\n// ===============================================================\r\n// PREÇO POR FETCH\r\n// ===============================================================\r\nexport function getPriceProd() {\r\n const selectors = document.querySelectorAll('[data-update-price]');\r\n const attr = 'data-update-price';\r\n\r\n if (selectors.length > 0) {\r\n selectors.forEach((selector) => {\r\n const prodId = selector.getAttribute(attr);\r\n const url = `/produto/preco/${prodId}`;\r\n\r\n if (prodId !== '' && prodId !== null) {\r\n fetch(url, {\r\n method: 'GET',\r\n })\r\n .then((response) => response.text())\r\n .then((resp) => {\r\n selector.innerHTML = resp;\r\n })\r\n .catch((error) => {\r\n console.error(error);\r\n });\r\n }\r\n });\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// DEBOUNCE\r\n// ===============================================================\r\n/*\r\n Debounce retorna uma função que enquanto continuar sendo chamada não é executada\r\n A função só será executada quando para de ser chamada por N milisegundos\r\n Útil para melhorar a performance de códigos que são executados muitas vezes por segundo, como o $(window).resize()\r\n\r\n Ex:\r\n \r\n $(window).resize(debounce(function() {\r\n // código a ser executado\r\n }, 500))\r\n \r\n No exemplo acima a função só será executada 500ms depois do último resize\r\n Abra o link abaixo e redimensione a janela branca e acompanhe o output do console\r\n Exemplo codepen: https://codepen.io/valkervieira/pen/oNgqyWY\r\n\r\n Um caso comum de uso é em lojas onde a seleção de um filtro na página de tag recarrega automáticamente a página\r\n Com o debounce o usuário pode escolher vários filtros rapidamente e a página só recarrega quando parar de escolher\r\n*/\r\n\r\nexport function debounce(func, wait, immediate) {\r\n var timeout;\r\n immediate || (immediate = true);\r\n\r\n return function () {\r\n var context = this,\r\n args = arguments;\r\n\r\n var later = function () {\r\n timeout = null;\r\n if (!immediate) func.apply(context, args);\r\n };\r\n\r\n var callNow = immediate && !timeout;\r\n\r\n clearTimeout(timeout);\r\n\r\n timeout = setTimeout(later, wait);\r\n\r\n if (callNow) func.apply(context, args);\r\n };\r\n}\r\n\r\n// ===============================================================\r\n// THROTTLE\r\n// ===============================================================\r\n/*\r\n Throttle diminui a frequencia que uma função é executada\r\n Enquanto no debounce a função só é executada quando para de ser chamada, no throttle ela\r\n continua sendo executada só que em um intervalo mínimo de N milisegundos (default = 250)\r\n\r\n Ex:\r\n\r\n $(window).resize(throttle() {\r\n // código a ser executado\r\n }, 500)\r\n\r\n No exemplo acima a função resize é chamada várias vezes por segundo mas só é executada 1 vez a cada 500ms\r\n Abra o link abaixo, redimensione a janela branca e acompanhe o console\r\n Exemplo codepen: https://codepen.io/valkervieira/pen/yLyKEPW\r\n\r\n Um caso comum de uso é checar se o scroll passou de um determinado ponto, para fixar um header ou alterar algum elemento do DOM\r\n*/\r\nexport function throttle(fn, threshhold, scope) {\r\n threshhold || (threshhold = 250);\r\n var last, deferTimer;\r\n return function () {\r\n var context = scope || this;\r\n\r\n var now = +new Date(),\r\n args = arguments;\r\n if (last && now < last + threshhold) {\r\n // hold on to it\r\n clearTimeout(deferTimer);\r\n deferTimer = setTimeout(function () {\r\n last = now;\r\n fn.apply(context, args);\r\n }, threshhold);\r\n } else {\r\n last = now;\r\n fn.apply(context, args);\r\n }\r\n };\r\n}\r\n\r\n// ===============================================================\r\n// FORMAT MONEY\r\n// ===============================================================\r\nexport function formatMoney(value) {\r\n // FORMATA UM VALOR\r\n return (\r\n 'R$ ' +\r\n value\r\n .toFixed(2)\r\n .replace('.', ',')\r\n .replace(/(\\d)(?=(\\d{3})+\\,)/g, '$1.')\r\n );\r\n}\r\n\r\n// ===============================================================\r\n// FORMAT VALUE\r\n// ===============================================================\r\n\r\nexport const formatValue = function (value = '') {\r\n let parsedValue = value;\r\n if (typeof value === 'number') {\r\n parsedValue = value.toFixed(2).toString();\r\n }\r\n return parsedValue.replace('.', ',');\r\n};\r\n\r\n// ===============================================================\r\n// VALIDA QUANTIDADE\r\n// ===============================================================\r\nexport function validateQuantity(_val) {\r\n // VALIDA SE A QUANTIDADE INFORMADA É UM NÚMERO\r\n if (!isNaN(_val)) {\r\n if (parseInt(_val) > 0) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ===============================================================\r\n// CLEAR NUMBER\r\n// ===============================================================\r\nexport function getClearNumber(_val) {\r\n // RETORNA UM NÚMERO LIMPO COMO INT\r\n if (!isNaN(_val)) {\r\n var clearNumber = parseInt(_val);\r\n\r\n return clearNumber;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// ===============================================================\r\n// BUSCA\r\n// ===============================================================\r\nexport function setSearch() {\r\n const toggleButton = document.querySelectorAll('[data-toggle-search]');\r\n const search = document.querySelector('[data-search-container]');\r\n const input = document.querySelector('[data-search-input]');\r\n const options = document.querySelector('[data-search-options]');\r\n\r\n toggleButton.length > 0 &&\r\n toggleButton.forEach((button) => {\r\n button.addEventListener('click', () => {\r\n if (search.classList.contains('open')) {\r\n search.classList.remove('open');\r\n } else {\r\n search.classList.add('open');\r\n setTimeout(() => {\r\n input.focus();\r\n }, 400);\r\n }\r\n });\r\n });\r\n \r\n if (input && options) {\r\n input.addEventListener('input', async () => {\r\n\r\n if (input.value && input.value != '') {\r\n if (options.innerHTML == '')\r\n try {\r\n const baseUrl = window.location.origin;\r\n const url = new URL(`/produto/quickview/4163`, baseUrl); // STG:5074 PROD:4163\r\n url.searchParams.set('search_value', input.value);\r\n url.searchParams.set('CC', Math.floor(Math.random() * 10000));\r\n \r\n const response = await fetch(url);\r\n const data = await response.text();\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(data, 'text/html');\r\n const results = doc.querySelector('[data-search-results]');\r\n \r\n if (results && results.innerHTML)\r\n options.innerHTML = results.innerHTML;\r\n \r\n } catch (error) { console.error(error) }\r\n \r\n let anchors = options.querySelectorAll('.anchor');\r\n if (anchors.length > 0) {\r\n let count = 0;\r\n anchors.forEach(anchor => {\r\n anchor.classList.remove('-active');\r\n if (anchor.getAttribute('data-name').includes(input.value.toLowerCase()) && count < 10) {\r\n anchor.classList.add('-active');\r\n count++;\r\n }\r\n });\r\n }\r\n\r\n } else {\r\n let anchors = options.querySelectorAll('.anchor');\r\n if (anchors.length > 0)\r\n anchors.forEach(anchor => { anchor.classList.remove('-active') });\r\n }\r\n });\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// BUSCA OS DADOS DO CLIENTE\r\n// ===============================================================\r\nexport async function getClient() {\r\n try {\r\n const response = await fetch('/conta/cliente', {\r\n headers: {\r\n accept: 'application/json',\r\n 'Content-Type': 'application/json',\r\n cache: 'no-store',\r\n },\r\n });\r\n const client = await response.json();\r\n const access = Object.keys(client).length > 0;\r\n\r\n if (access) {\r\n window.client = client;\r\n\r\n return client;\r\n } else {\r\n return null;\r\n }\r\n } catch (error) {\r\n console.error(`getClient error`, error);\r\n }\r\n}\r\n\r\n// ===============================================================\r\n// MÁSCARA PARA INPUTS\r\n// ===============================================================\r\nexport function formMasks() {\r\n const inputPhones = document.querySelectorAll('[data-phone-mask]'),\r\n inputCEPs = document.querySelectorAll('[data-cep-mask]'),\r\n inputCPFs = document.querySelectorAll('[data-cpf-mask]'),\r\n inputCNPJs = document.querySelectorAll('[data-cnpj-mask]'),\r\n inputDatesOfBirth = document.querySelectorAll('[data-birth-mask]');\r\n\r\n inputPhones.length > 0 &&\r\n inputPhones.forEach((input) => {\r\n input.addEventListener('input', (e) => {\r\n //(XX) XXXXX-XXXX\r\n var phoneValue = e.target.value.replace(/\\D/g, '').match(/(\\d{0,2})(\\d{0,5})(\\d{0,4})/);\r\n e.target.value = !phoneValue[2]\r\n ? phoneValue[1]\r\n : '(' + phoneValue[1] + ') ' + phoneValue[2] + (phoneValue[3] ? '-' + phoneValue[3] : '');\r\n });\r\n });\r\n\r\n inputCEPs.length > 0 &&\r\n inputCEPs.forEach((input) => {\r\n input.addEventListener('input', (e) => {\r\n //XXXXX-XX\r\n var cepValue = e.target.value.replace(/\\D/g, '').match(/(\\d{0,5})(\\d{0,3})/);\r\n e.target.value = !cepValue[2] ? cepValue[1] : cepValue[1] + '-' + cepValue[2];\r\n });\r\n });\r\n\r\n inputCPFs.length > 0 &&\r\n inputCPFs.forEach((input) => {\r\n input.addEventListener('input', (e) => {\r\n //XXX.XXX.XXX-XX\r\n var cpfValue = e.target.value.replace(/\\D/g, '').match(/(\\d{0,3})(\\d{0,3})(\\d{0,3})(\\d{0,2})/);\r\n e.target.value = !cpfValue[2]\r\n ? cpfValue[1]\r\n : cpfValue[1] +\r\n '.' +\r\n cpfValue[2] +\r\n (cpfValue[3] ? '.' + cpfValue[3] : '') +\r\n (cpfValue[4] ? '-' + cpfValue[4] : '');\r\n });\r\n });\r\n\r\n inputCNPJs.length > 0 &&\r\n inputCNPJs.forEach((input) => {\r\n input.addEventListener('input', (e) => {\r\n //XX.XXX.XXX/XXXX-XX\r\n var cnpjValue = e.target.value.replace(/\\D/g, '').match(/(\\d{0,2})(\\d{0,3})(\\d{0,3})(\\d{0,4})(\\d{0,2})/);\r\n e.target.value = !cnpjValue[2]\r\n ? cnpjValue[1]\r\n : cnpjValue[1] +\r\n '.' +\r\n cnpjValue[2] +\r\n (cnpjValue[3] ? '.' + cnpjValue[3] : '') +\r\n (cnpjValue[4] ? '/' + cnpjValue[4] : '') +\r\n (cnpjValue[5] ? '-' + cnpjValue[5] : '');\r\n });\r\n });\r\n\r\n inputDatesOfBirth.length > 0 &&\r\n inputDatesOfBirth.forEach((input) => {\r\n input.addEventListener('input', (e) => {\r\n // XXXX-XX-XX\r\n var dateOfBirthValue = e.target.value.replace(/\\D/g, '').match(/(\\d{0,2})(\\d{0,2})(\\d{0,4})/);\r\n e.target.value = !dateOfBirthValue[2]\r\n ? dateOfBirthValue[1]\r\n : dateOfBirthValue[1] + '/' + dateOfBirthValue[2] + (dateOfBirthValue[3] ? '/' + dateOfBirthValue[3] : '');\r\n });\r\n });\r\n}\r\n\r\nexport function videoLazy() {\r\n const videos = document.querySelectorAll('[data-video-banner]');\r\n\r\n if (videos.length > 0) {\r\n videos.forEach((video) => {\r\n const addSrcVideo = () => {\r\n const urlVideo = video.getAttribute('data-video-banner');\r\n const iframe = video.querySelector('iframe');\r\n\r\n if (iframe && urlVideo) {\r\n iframe.setAttribute('src', urlVideo);\r\n //console.log('Vídeo carregado:', urlVideo);\r\n\r\n // Remove os event listeners após carregar o vídeo\r\n window.removeEventListener('mousemove', addSrcVideo);\r\n window.removeEventListener('scroll', addSrcVideo);\r\n }\r\n };\r\n\r\n // Adiciona os event listeners\r\n window.addEventListener('mousemove', addSrcVideo);\r\n window.addEventListener('scroll', addSrcVideo);\r\n });\r\n }\r\n}\r\n","import { addAsset } from '../components/utilities';\r\n\r\nconst CartDrawer = {\r\n root: document.querySelector('#component-cart-drawer-root'),\r\n buttons: document.querySelectorAll('[data-toggle-cart]'),\r\n countWrapper: document.querySelector('[data-cart-count]'),\r\n settings: window.cartDrawerSettings || false,\r\n\r\n setCartDrawer: function () {\r\n const { settings, root } = CartDrawer;\r\n\r\n if (!root || !settings) return;\r\n\r\n // Define frete grátis\r\n const freeShipping = settings.freeShippingValue > 1 ? settings.freeShippingValue : 0;\r\n\r\n // Inicia o componente\r\n const componentCartDrawer = new Vnda.Component.CartDrawer({\r\n anchor: 'right',\r\n display: 'list',\r\n startOpen: false,\r\n titleCart: 'Carrinho de compras',\r\n titleSuggested: window.cartDrawerSettings.titleSuggested,\r\n suggestedProductsTag: 'sugestoes-carrinho',\r\n widthItemSuggested: 25,\r\n disableShippingCalculation: true,\r\n freeShipping,\r\n });\r\n\r\n // Renderiza o componente\r\n componentCartDrawer.render(root);\r\n\r\n // Salva instância para acesso global\r\n window.cartDrawerSettings.instance = componentCartDrawer;\r\n CartDrawer.settings = window.cartDrawerSettings;\r\n\r\n // dispara evento de carregamento, escutado por CartDrawer.show()\r\n root.dispatchEvent(new Event('vnda:cart-drawer-loaded'));\r\n },\r\n\r\n loadComponent: function () {\r\n const { settings } = CartDrawer;\r\n addAsset(settings.script, CartDrawer.setCartDrawer);\r\n addAsset(settings.styles);\r\n },\r\n\r\n handleCartButton: function (button) {\r\n // Evita múltiplos cliques caso o carrinho precisa ser instanciado primeiro\r\n if (button.classList.contains('-loading')) {\r\n return;\r\n }\r\n\r\n // Abre o cart drawer\r\n button.classList.add('-loading');\r\n CartDrawer.show(() => {\r\n button.classList.remove('-loading');\r\n });\r\n },\r\n\r\n show: function (callback) {\r\n const { root } = CartDrawer;\r\n\r\n // No mobile, fecha o menu primeiro\r\n if (window.mmenu) window.mmenu.close();\r\n\r\n // Instancia o componente, caso ainda não exista\r\n if (!CartDrawer.settings.instance) CartDrawer.loadComponent();\r\n\r\n // Observa criação da instância inicial, caso não tenha\r\n if (CartDrawer.settings.instance === false) {\r\n root.addEventListener('vnda:cart-drawer-loaded', () => {\r\n CartDrawer.settings.instance.open();\r\n if (typeof callback === 'function') callback();\r\n });\r\n } else {\r\n // Já possui cart drawer instanciado, retorna abertura\r\n CartDrawer.settings.instance.open();\r\n if (typeof callback === 'function') callback();\r\n }\r\n },\r\n\r\n getCartItens: async function () {\r\n try {\r\n const response = await fetch('/carrinho/itens');\r\n const itens = await response.json();\r\n return itens;\r\n } catch (error) {\r\n console.error('Erro ao buscar a quantidade de produtos do carrinho');\r\n console.error(error);\r\n return 0;\r\n }\r\n },\r\n\r\n updateCartCount: async function (_itemsCount = null) {\r\n let items = _itemsCount;\r\n if (_itemsCount == null) items = await CartDrawer.getCartItens();\r\n\r\n this.countWrapper.innerHTML = items;\r\n },\r\n\r\n init: function () {\r\n const _this = this;\r\n const { buttons } = _this;\r\n\r\n // Atualiza o contador de itens do carrinho\r\n _this.updateCartCount();\r\n\r\n if (buttons.length > 0)\r\n buttons.forEach((button) => {\r\n button.addEventListener('click', () => {\r\n _this.handleCartButton(button);\r\n });\r\n });\r\n },\r\n};\r\n\r\nexport default CartDrawer;\r\n","import CartDrawer from '../common/cartDrawer';\r\nimport { urlencodeFormData } from './utilities';\r\n\r\nconst Store = {\r\n openCartDrawer: true,\r\n openCartDrawerMobile: true,\r\n\r\n addProduct: function(form, parent, callback) {\r\n // Se tiver customizações, ajusta campos de texto que não foram preenchidos\r\n const customizations = form.querySelectorAll('[data-customization]')\r\n const quantity = Number(form.querySelector('[name=\"quantity\"]').value)\r\n if (customizations.length > 0) customizations.forEach(custom => {\r\n const type = custom.getAttribute('type')\r\n\r\n if (type !== 'checkbox' || type !== 'radio') {\r\n if (custom.value === '') {\r\n custom.setAttribute('disabled', true)\r\n }\r\n }\r\n })\r\n\r\n if (customizations.length > 0 && quantity > 1) {\r\n // Item com personalização e com quantidade alta\r\n Store.addItemsCustom(form, parent, callback)\r\n } else {\r\n // Item com quantidade 1, com ou sem personalização\r\n Store.addItem(form, parent, callback)\r\n }\r\n },\r\n\r\n addItemsCustom: async function(form, parent, callback) {\r\n const _this = this;\r\n const btnComprar = parent.querySelector('[data-action=\"add-cart\"]');\r\n const boxResponse = parent.querySelector('[data-form-product] .msg-response:not(.resp-validate)');\r\n const quantity = Number(form.querySelector('[name=\"quantity\"]').value)\r\n let hasCustoms = false\r\n let customs = {}\r\n\r\n // Prepara o item e suas personalizações\r\n let data = { items: [\r\n {\r\n sku: form.querySelector('[name=\"sku\"]').value,\r\n quantity,\r\n customizations: []\r\n }\r\n ]}\r\n\r\n const customizations = form.querySelectorAll('[data-customization]')\r\n if (customizations.length > 0) customizations.forEach(custom => {\r\n const disabled = custom.getAttribute('disabled')\r\n const type = custom.getAttribute('type')\r\n let checked = true;\r\n if (type !== 'text' && type !== 'textarea') checked = custom.checked\r\n\r\n if (checked && disabled !== 'true') {\r\n hasCustoms = true\r\n if (type === 'text' || type === 'textarea') {\r\n customs[custom.getAttribute('data-customization-name')] = custom.value\r\n } else {\r\n customs[custom.getAttribute('data-customization-name')] = custom.getAttribute('value') \r\n }\r\n }\r\n })\r\n\r\n if (hasCustoms) {\r\n for (let index = 0; index < quantity; index++) {\r\n data.items[0].customizations.push(customs)\r\n }\r\n }\r\n\r\n const json_data = JSON.stringify(data)\r\n\r\n console.info('addItemsCustom');\r\n // console.log(json_data)\r\n\r\n // Envia o produto com suas personalizações\r\n if (!btnComprar.classList.contains('-adding')) {\r\n btnComprar.classList.add('-adding')\r\n\r\n try {\r\n const response = await fetch('/carrinho/adicionar/kit', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: json_data,\r\n });\r\n \r\n const html = await response.text();\r\n\r\n if (response.ok) {\r\n console.log('addItemsCustom - success');\r\n if (typeof callback == 'function') {\r\n callback('produto-adicionado', html, boxResponse, form);\r\n } else {\r\n _this.addItemResult('produto-adicionado', html, boxResponse, form);\r\n }\r\n\r\n } else {\r\n console.log('addItemsCustom - server não reconheceu adição');\r\n if (typeof callback == 'function') {\r\n callback('erro-adicionar', error, boxResponse, form);\r\n } else {\r\n _this.addItemResult('erro-adicionar', error, boxResponse, form);\r\n }\r\n }\r\n\r\n } catch (error) {\r\n console.log('addItemsCustom - error');\r\n console.error(error);\r\n\r\n if (typeof callback == 'function') {\r\n callback('erro-adicionar', error, boxResponse, form);\r\n } else {\r\n _this.addItemResult('erro-adicionar', error, boxResponse, form);\r\n }\r\n }\r\n\r\n customizations.forEach(custom => {\r\n custom.removeAttribute('disabled')\r\n })\r\n\r\n btnComprar.classList.remove('-adding');\r\n }\r\n },\r\n\r\n addItem: async function (form, parent, callback) {\r\n const _this = this;\r\n const btnComprar = parent.querySelector('[data-action=\"add-cart\"]');\r\n const urlAdd = '/carrinho/adicionar';\r\n const formData = urlencodeFormData(new FormData(form));\r\n const boxResponse = parent.querySelector('[data-form-product] .msg-response:not(.resp-validate)');\r\n\r\n console.info('addItem');\r\n\r\n if (!btnComprar.classList.contains('-adding')) {\r\n btnComprar.classList.add('-adding');\r\n\r\n try {\r\n const response = await fetch(urlAdd, {\r\n method: 'POST',\r\n headers: {\r\n 'Accept': 'application/json, text/javascript, */*; q=0.0',\r\n 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',\r\n },\r\n body: formData,\r\n });\r\n\r\n const html = await response.text();\r\n\r\n console.log('addItem - success');\r\n\r\n if (typeof callback == 'function') {\r\n callback('produto-adicionado', html, boxResponse, form);\r\n } else {\r\n _this.addItemResult('produto-adicionado', html, boxResponse, form);\r\n }\r\n } catch (error) {\r\n console.log('addItem - error');\r\n console.error(error);\r\n\r\n if (typeof callback == 'function') {\r\n callback('erro-adicionar', error, boxResponse, form);\r\n } else {\r\n _this.addItemResult('erro-adicionar', error, boxResponse, form);\r\n }\r\n }\r\n\r\n btnComprar.classList.remove('-adding');\r\n }\r\n },\r\n\r\n deleteItem: async function (itemId, item, removeItemResult) {\r\n const _this = this;\r\n\r\n try {\r\n const body = new URLSearchParams({\r\n _method: 'DELETE',\r\n item_id: itemId\r\n });\r\n\r\n const response = await fetch('/carrinho', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',\r\n 'Accept': 'application/json, text/javascript, */*; q=0.01',\r\n },\r\n body\r\n })\r\n\r\n console.log('success');\r\n \r\n if (window.innerWidth > 768) {\r\n if (_this.openCartDrawer) {\r\n CartDrawer.updateCartCount();\r\n }\r\n } else {\r\n if (_this.openCartDrawerMobile) {\r\n CartDrawer.updateCartCount();\r\n }\r\n }\r\n\r\n if (typeof removeItemResult == 'function') {\r\n removeItemResult(item);\r\n }\r\n } catch (error) {\r\n console.log('Erro ao remover item do carrinho');\r\n console.log(error);\r\n }\r\n },\r\n\r\n validateFormProduct: function (form) {\r\n // VALIDA O FORM DE PRODUTO PARA VER SE O PRODUTO PODE SER ADICIONADO\r\n var btnComprar = form.querySelector('[data-action=\"add-cart\"]');\r\n var validated = true;\r\n var errors = [];\r\n\r\n if (btnComprar.dataset.available == 'false') {\r\n validated = false;\r\n errors.push('');\r\n } else {\r\n // verifica se o sku foi selecionado\r\n if (form.querySelector('[name=\"sku\"]').value == '') {\r\n validated = false;\r\n errors.push('Selecione um atributo para o produto');\r\n }\r\n\r\n // verifica se a quantidade é válida\r\n if (form.querySelector('input[name=\"quantity\"]').value <= 0) {\r\n validated = false;\r\n errors.push('Quantidade indisponível');\r\n }\r\n }\r\n\r\n return { validated, errors };\r\n },\r\n\r\n setRespValidateProduct: function (resp, form, boxResponse) {\r\n let htmlErrors = '';\r\n\r\n if (resp.validated) {\r\n boxResponse.innerHTML = '';\r\n } else {\r\n for (var i = resp.errors.length - 1; i >= 0; i--) {\r\n htmlErrors += '' + resp.errors[i] + '';\r\n }\r\n boxResponse.innerHTML = htmlErrors;\r\n }\r\n },\r\n\r\n addItemResult: function (typeResult, result, boxResponse, form) {\r\n const _this = this;\r\n\r\n if (typeResult == 'produto-adicionado') {\r\n const btnComprar = form.querySelector('[data-action=\"add-cart\"]');\r\n\r\n if (btnComprar) btnComprar.classList.add('success');\r\n\r\n setTimeout(function () {\r\n if (btnComprar) btnComprar.classList.remove('success');\r\n if (btnComprar) btnComprar.innerHTML = btnComprar.dataset.textAvailable;\r\n }, 3500);\r\n\r\n // CartDrawer.updateCartCount();\r\n\r\n if (window.innerWidth > 768) {\r\n if (_this.openCartDrawer) {\r\n CartDrawer.show();\r\n } else {\r\n setTimeout(() => {\r\n window.location.href = urlCart;\r\n }, 150);\r\n }\r\n } else {\r\n if (_this.openCartDrawerMobile) {\r\n CartDrawer.show();\r\n } else {\r\n setTimeout(() => {\r\n window.location.href = urlCart;\r\n }, 150);\r\n }\r\n }\r\n\r\n // Verifica se há popup de compra rápida ativo. Se tiver, fecha ele\r\n // Retirar ou comentar se não for utilizado\r\n const popupQuickview = document.querySelectorAll('[data-popup-quickview]');\r\n popupQuickview.length > 0 && popupQuickview.forEach(popup => {\r\n if (popup.classList.contains('-active')) {\r\n popup.querySelector('[data-close-popup-quickview]').click();\r\n }\r\n })\r\n\r\n // Remove disabled das personalizações de texto, se existirem\r\n const customizations = form.querySelectorAll('[data-customization]')\r\n if (customizations.length > 0) customizations.forEach(custom => {\r\n const type = custom.getAttribute('type')\r\n if (type !== 'checkbox' || type !== 'radio') {\r\n custom.removeAttribute('disabled')\r\n }\r\n })\r\n \r\n } else if (typeResult == 'erro-adicionar') {\r\n if (typeof boxResponse != 'undefined' && boxResponse.length > 0) {\r\n window.scrollTo({\r\n top: boxResponse.offsetTop,\r\n behavior: 'smooth',\r\n });\r\n\r\n boxResponse.classList.add('error');\r\n boxResponse.classList.remove('success');\r\n boxResponse.querySelector('span').innerHTML =\r\n 'Ocorreu um erro, tente novamente.';\r\n }\r\n }\r\n },\r\n};\r\n\r\nexport default Store;\r\n","// \"productVariants\" é inicializado em layout.liquid, e todos os arquivos liquid que montam\r\n// product_block populam este objeto com as variantes dos produtos em tela\r\nimport Store from './components/store';\r\n\r\nconst ProductPurchase = {\r\n productVariants,\r\n products: document.querySelectorAll('[data-product-box]'),\r\n useLocals: false, // Venda por Locais: alterar para habilitar a funcionalidade - true/false \r\n\r\n // Verifica as combinações possíveis entre os atributos, com base no atributo que foi clicado\r\n checkCombinations: function (currentProduct, selectedAttribute) {\r\n const productId = currentProduct.getAttribute('data-product-id');\r\n const selectedAttr = Number(selectedAttribute.getAttribute('data-attribute-index'));\r\n const variants = ProductPurchase.productVariants[`${productId}`];\r\n\r\n // Busca todos os atributos do produto\r\n const attributes = {\r\n attr1: [...currentProduct.querySelectorAll('[data-attribute-index=\"1\"]')],\r\n attr2: [...currentProduct.querySelectorAll('[data-attribute-index=\"2\"]')],\r\n attr3: [...currentProduct.querySelectorAll('[data-attribute-index=\"3\"]')],\r\n };\r\n\r\n // Busca os atuais atributos selecionados\r\n const selectedAttributes = {\r\n attr1: currentProduct.querySelector('[data-attribute=\"1\"] input:checked + label'),\r\n attr2: currentProduct.querySelector('[data-attribute=\"2\"] input:checked + label'),\r\n attr3: currentProduct.querySelector('[data-attribute=\"3\"] input:checked + label'),\r\n };\r\n\r\n // Altera o selected para o atributo que foi clicado\r\n selectedAttributes[`attr${selectedAttr}`] = selectedAttribute;\r\n\r\n // Atualiza as classes dos atributos disponíveis/indisponíveis\r\n // Ao clicar em uma opção de attr1, atualiza os attrs 2 e 3\r\n switch (selectedAttr) {\r\n case 1:\r\n ProductPurchase.markAttributes([...attributes.attr2], 2, variants, selectedAttributes, currentProduct);\r\n ProductPurchase.markAttributes([...attributes.attr3], 3, variants, selectedAttributes, currentProduct);\r\n break;\r\n\r\n case 2:\r\n ProductPurchase.markAttributes([...attributes.attr3], 3, variants, selectedAttributes, currentProduct);\r\n break;\r\n\r\n case 3:\r\n break;\r\n }\r\n },\r\n\r\n // Marca os atributos como disponiveis/indisponiveis com base nas combinações do checkCombinations\r\n markAttributes: function (attributes, index, variants, selectedAttributes, currentProduct) {\r\n if (attributes != null && attributes.length > 0) {\r\n // Remove os atributos já selecionados que não devem ser analizados,\r\n // com base no index do atributo que está sendo analizado. Usado para filtrar\r\n // as variantes e diminuir o número de possíveis combinações que definem como disponível/indisponível\r\n switch (index) {\r\n case 1:\r\n selectedAttributes.attr2 = null;\r\n selectedAttributes.attr3 = null;\r\n break;\r\n\r\n case 2:\r\n selectedAttributes.attr3 = null;\r\n break;\r\n\r\n case 3:\r\n break;\r\n }\r\n\r\n attributes.forEach((attr) => {\r\n const value = attr.getAttribute('data-attribute-value');\r\n const property = `property${index}`;\r\n let available = false;\r\n\r\n // Adiciona o atributo iterado nos atributos usados para buscar variantes válidas\r\n const attrsToCheck = {\r\n ...selectedAttributes,\r\n [`attr${index}`]: attr,\r\n };\r\n\r\n // Filtra as variantes para somente as que possuem a combinação de atributos válida\r\n const validVariants = variants.filter((variant) => {\r\n const properties = variant.properties;\r\n let validAttr1 = false;\r\n let validAttr2 = false;\r\n let validAttr3 = false;\r\n\r\n if (attrsToCheck.attr1 == null) validAttr1 = true;\r\n if (attrsToCheck.attr2 == null) validAttr2 = true;\r\n if (attrsToCheck.attr3 == null) validAttr3 = true;\r\n\r\n if (properties.property1 == null) validAttr1 = true;\r\n if (properties.property2 == null) validAttr2 = true;\r\n if (properties.property3 == null) validAttr3 = true;\r\n\r\n if (validAttr1 == false) {\r\n const valueToCheck = attrsToCheck.attr1.getAttribute('data-attribute-value');\r\n if (properties.property1.value == valueToCheck) validAttr1 = true;\r\n }\r\n\r\n if (validAttr2 == false) {\r\n const valueToCheck = attrsToCheck.attr2.getAttribute('data-attribute-value');\r\n if (properties.property2.value == valueToCheck) validAttr2 = true;\r\n }\r\n\r\n if (validAttr3 == false) {\r\n const valueToCheck = attrsToCheck.attr3.getAttribute('data-attribute-value');\r\n if (properties.property3.value == valueToCheck) validAttr3 = true;\r\n }\r\n\r\n if (validAttr1 && validAttr2 && validAttr3) return variant;\r\n });\r\n\r\n attr.classList.remove('-available');\r\n attr.classList.remove('-unavailable');\r\n attr.classList.remove('-disabled');\r\n\r\n if (validVariants.length > 0) {\r\n // Encontrou variantes, marca como disponível/indisponível com base nas variantes\r\n for (const variant of validVariants) {\r\n if (variant.properties[property]) {\r\n if (variant.properties[property].value == value) {\r\n\r\n // Venda por Locais\r\n // Busca informações da variante de acordo com o local selecionado\r\n let variantInventory = null;\r\n if (window.currentLocal) {\r\n variantInventory = variant.inventories.find(inventory => {\r\n return inventory.place && inventory.place.id && inventory.place.id === window.currentLocal.id;\r\n });\r\n\r\n } else if (ProductPurchase.useLocals) {\r\n // Sem local definido, busca por estoque em algum dos locais\r\n variantInventory = variant.inventories.find(inventory => {\r\n return inventory.available;\r\n });\r\n }\r\n\r\n if ((variantInventory && variantInventory.available) || (!variantInventory && variant.available)) {\r\n available = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n available ? attr.classList.add('-available') : attr.classList.add('-unavailable');\r\n } else if (validVariants.length === 0) {\r\n // Não encontrou nenhuma variante, então desabilita a opção.\r\n // Se esta opção estava selecionada, clica na primeira opção disponível entre os demais\r\n attr.classList.add('-disabled');\r\n const value = attr.getAttribute('data-attribute-value');\r\n const input = currentProduct.querySelector(`[data-attribute=\"${index}\"] input[value=\"${value}\"]`);\r\n if (input.checked) {\r\n input.checked = false;\r\n setTimeout(() => {\r\n const firstAvailable = currentProduct.querySelector(\r\n `label[data-attribute-index=\"${index}\"]:not(.-disabled)`\r\n );\r\n if (firstAvailable) firstAvailable.click();\r\n }, 50);\r\n }\r\n }\r\n });\r\n }\r\n },\r\n\r\n // Procura por SKU válido dentre os atributos escolhidos\r\n checkSelection: function (currentProduct) {\r\n const productId = currentProduct.getAttribute('data-product-id');\r\n const variants = ProductPurchase.productVariants[`${productId}`];\r\n\r\n const selectedAttrs = {\r\n attr1: currentProduct.querySelector('[data-attribute=\"1\"] input:checked'),\r\n attr2: currentProduct.querySelector('[data-attribute=\"2\"] input:checked'),\r\n attr3: currentProduct.querySelector('[data-attribute=\"3\"] input:checked'),\r\n };\r\n\r\n let available = false;\r\n\r\n for (let index = 0; index < variants.length; index++) {\r\n const variant = variants[index];\r\n let attr1 = false;\r\n let attr2 = false;\r\n let attr3 = false;\r\n let attr1Value = null;\r\n let attr2Value = null;\r\n let attr3Value = null;\r\n\r\n // Venda por Locais\r\n // Busca informações da variante de acordo com o local selecionado\r\n let variantInventory = null;\r\n if (window.currentLocal) {\r\n variantInventory = variant.inventories.find(inventory => {\r\n return inventory.place && inventory.place.id && inventory.place.id === window.currentLocal.id;\r\n });\r\n }\r\n\r\n // Verifica se algum dos atributos é inexistente no cadastro\r\n if (variant.properties.property1 == null) attr1 = true;\r\n if (variant.properties.property2 == null) attr2 = true;\r\n if (variant.properties.property3 == null) attr3 = true;\r\n\r\n //Salva o valor de cada um dos atributos/propriedes da própria variante em questão\r\n if (variant.properties.property1) attr1Value = variant.properties.property1.value;\r\n if (variant.properties.property2) attr2Value = variant.properties.property2.value;\r\n if (variant.properties.property3) attr3Value = variant.properties.property3.value;\r\n\r\n // Verifica se a variante possui os atributos selecionados\r\n if (!attr1 && attr1Value != null && selectedAttrs.attr1 != null) {\r\n if (attr1Value == selectedAttrs.attr1.value) attr1 = true;\r\n }\r\n\r\n if (!attr2 && attr2Value != null && selectedAttrs.attr2 != null) {\r\n if (attr2Value == selectedAttrs.attr2.value) attr2 = true;\r\n }\r\n\r\n if (!attr3 && attr3Value != null && selectedAttrs.attr3 != null) {\r\n if (attr3Value == selectedAttrs.attr3.value) attr3 = true;\r\n }\r\n\r\n // Se achou variante compatível com os atributos selecionados, atualiza\r\n if (attr1 && attr2 && attr3) {\r\n available = true;\r\n const event = new CustomEvent('vnda:sku-change', { detail: { sku: variant.sku } });\r\n const productContainer = currentProduct.closest('[data-product-box]');\r\n\r\n currentProduct.querySelector('[name=\"sku\"]').value = variant.sku;\r\n currentProduct.dispatchEvent(event);\r\n if (productContainer) productContainer.dispatchEvent(event);\r\n\r\n // Reinicializa o input de quantidade para 1\r\n currentProduct.querySelector('[name=\"quantity\"]').value = 1;\r\n\r\n // Remove a mensagem de quantidade máxima quando altera a variante\r\n if (currentProduct.querySelector('.msg-response .msg-error').classList.contains('-visible')) {\r\n currentProduct.querySelector('.msg-response .msg-error').innerHTML = '';\r\n currentProduct.querySelector('.msg-response .msg-error').classList.remove('-visible');\r\n }\r\n\r\n // Quantidade da variante\r\n let variantQuantity = variant.available_quantity;\r\n if (variantInventory) {\r\n variantQuantity = variantInventory.quantity;\r\n }\r\n\r\n // Configura a quantidade máxima do input conforme a variante selecionada\r\n currentProduct.querySelector('[name=\"quantity\"]').setAttribute('data-available-quantity', variantQuantity);\r\n\r\n\r\n // Configura produto disponível/indisponível\r\n if (variant.available && !variantInventory) {\r\n ProductPurchase.setAvailable(currentProduct);\r\n\r\n } else if (variant.available && variantInventory && variantInventory.available) {\r\n ProductPurchase.setAvailable(currentProduct);\r\n\r\n } else if (!variant.available && variantInventory && variantInventory.available) {\r\n ProductPurchase.setAvailable(currentProduct);\r\n\r\n } else if (!variant.available && !variantInventory && ProductPurchase.useLocals) {\r\n \r\n // Variante indisponível, sem local selecionado, porém com estoque em algum dos locais\r\n let variantInventory = null;\r\n variantInventory = variant.inventories.find(inventory => {\r\n return inventory.available;\r\n });\r\n\r\n if (variantInventory) ProductPurchase.setAvailable(currentProduct);\r\n\r\n } else {\r\n ProductPurchase.setUnavailable(currentProduct, true, variant.sku);\r\n }\r\n\r\n // Atualiza as últimas quantidades disponíveis\r\n ProductPurchase.setLastUnits(currentProduct, variant, variantInventory);\r\n\r\n // Atualiza o preço do componente\r\n ProductPurchase.updatePrice(currentProduct, variant, variantInventory);\r\n\r\n break;\r\n }\r\n }\r\n\r\n // Quando não encontra variante\r\n if (!available) ProductPurchase.setUnavailable(currentProduct, false);\r\n },\r\n\r\n // Define produto como disponível pra compra\r\n setAvailable: function (currentProduct) {\r\n const addButton = currentProduct.querySelector('[data-action=\"add-cart\"]');\r\n const currentProductWrapper = currentProduct.closest('[data-product-box]');\r\n let formNotify = null;\r\n let formNotifyParent = null;\r\n\r\n if (currentProductWrapper) {\r\n formNotify = currentProductWrapper.querySelector('[data-form-notify]');\r\n if (formNotify)\r\n formNotifyParent = formNotify.parentElement;\r\n }\r\n\r\n if (addButton) {\r\n // addButton.setAttribute('data-available', true);\r\n addButton.classList.add('-available');\r\n addButton.classList.remove('-unavailable');\r\n addButton.innerHTML = addButton.getAttribute('data-text-available');\r\n }\r\n\r\n if (formNotify) formNotify.classList.remove('-active');\r\n if (formNotifyParent) formNotifyParent.classList.remove('-active');\r\n },\r\n\r\n // Define produto como indisponível pra compra\r\n setUnavailable: function (currentProduct, showNotify, sku) {\r\n const addButton = currentProduct.querySelector('[data-action=\"add-cart\"]');\r\n const currentProductWrapper = currentProduct.closest('[data-product-box]');\r\n const showFormNotify = showNotify || false;\r\n let formNotify = null;\r\n let formNotifyParent = null;\r\n\r\n if (currentProductWrapper) {\r\n formNotify = currentProductWrapper.querySelector('[data-form-notify]');\r\n if (formNotify)\r\n formNotifyParent = formNotify.parentElement;\r\n }\r\n\r\n if (addButton) {\r\n // addButton.setAttribute('data-available', false);\r\n addButton.classList.remove('-available');\r\n addButton.classList.add('-unavailable');\r\n addButton.innerHTML = addButton.getAttribute('data-text-unavailable');\r\n }\r\n\r\n if (formNotify) {\r\n if (showFormNotify && sku != undefined && sku != null) {\r\n formNotify.classList.add('-active');\r\n formNotify.querySelector('[name=\"sku\"]').value = sku;\r\n if (formNotifyParent) formNotifyParent.classList.add('-active');\r\n } else {\r\n formNotify.classList.remove('-active');\r\n if (formNotifyParent) formNotifyParent.classList.remove('-active');\r\n }\r\n }\r\n },\r\n\r\n // Atualiza o componente de preço do produto\r\n updatePrice: function (currentProduct, variant, inventory) {\r\n const productMainContainer = currentProduct.closest('[data-product-box]');\r\n if (productMainContainer == null) return;\r\n\r\n const priceEl = productMainContainer.querySelector('[data-init-price]');\r\n if (priceEl == null) return;\r\n\r\n const groupShop = productMainContainer.getAttribute('data-prod-group-shop');\r\n\r\n // Utiliza o preço da variante ou do local selecionado, caso exista\r\n const variantPrice = inventory ? inventory.price : variant.price;\r\n const variantSalePrice = inventory ? inventory.sale_price : variant.sale_price;\r\n\r\n priceEl.setAttribute('data-sku', variant.sku);\r\n priceEl.setAttribute('data-price', variantPrice);\r\n priceEl.dispatchEvent(new Event('change'));\r\n\r\n const discount = priceEl.dataset.discountPercent;\r\n\r\n // Coloca a porcentagem de desconto no produto\r\n if (discount != '0') {\r\n priceEl.style.setProperty('--discount', `'-${discount}%'`);\r\n }\r\n\r\n // atualiza preço final do compre junto se existir\r\n if (groupShop != null) {\r\n\r\n const isAvailable =\r\n (variant.available && !inventory) ||\r\n (variant.available && inventory && inventory.available) ||\r\n (!variant.available && inventory && inventory.available);\r\n\r\n productMainContainer.setAttribute('data-price', variantPrice);\r\n productMainContainer.setAttribute('data-sale-price', variantSalePrice);\r\n productMainContainer.setAttribute('data-available', isAvailable);\r\n productMainContainer.dispatchEvent(new Event('vnda:group-shop-price-update'));\r\n }\r\n },\r\n\r\n // Marca o primeiro atributo como disponível/indisponível, e seleciona os atributos\r\n // da primeira variante disponível\r\n markFirstVariant: function (currentProduct) {\r\n const productId = currentProduct.getAttribute('data-product-id');\r\n const variants = [...ProductPurchase.productVariants[`${productId}`]];\r\n\r\n if (variants.length === 1) {\r\n\r\n // Venda por Locais\r\n let variantInventory = null;\r\n // Busca informações da variante de acordo com o local selecionado\r\n if (window.currentLocal) {\r\n variantInventory = variants[0].inventories.find(inventory => {\r\n return inventory.place && inventory.place.id && inventory.place.id === window.currentLocal.id;\r\n });\r\n\r\n } else if (!variants[0].available && ProductPurchase.useLocals) {\r\n // Verifica se o estoque da variante está indisponível\r\n // Busca disponibilidade em algum dos locais - Se encontrar, habilita o produto\r\n variantInventory = variants[0].inventories.find(inventory => {\r\n return inventory.available;\r\n });\r\n }\r\n\r\n // Possui somente uma variante e não possui atributos,\r\n // define como disponível/indisponível com base na variante em si\r\n if (currentProduct.querySelectorAll('.prod-option').length === 0) {\r\n\r\n // Quantidade da variante\r\n let variantQuantity = variants[0].available_quantity;\r\n if (variantInventory) {\r\n variantQuantity = variantInventory.quantity;\r\n }\r\n\r\n // Configura a quantidade máxima do input conforme a variante selecionada\r\n currentProduct\r\n .querySelector('[name=\"quantity\"]')\r\n .setAttribute('data-available-quantity', variantQuantity);\r\n\r\n // Atualiza o preço do componente\r\n ProductPurchase.updatePrice(currentProduct, variants[0], variantInventory);\r\n\r\n // Atualiza as últimas quantidades disponíveis\r\n ProductPurchase.setLastUnits(currentProduct, variants[0], variantInventory);\r\n\r\n return (\r\n (variants[0].available && !variantInventory) ||\r\n (variants[0].available && variantInventory && variantInventory.available) ||\r\n (!variants[0].available && variantInventory && variantInventory.available)\r\n ) ? ProductPurchase.setAvailable(currentProduct)\r\n : ProductPurchase.setUnavailable(currentProduct, true, variants[0].sku);\r\n\r\n } else {\r\n // Possui somente uma variante e possui atributos,\r\n\r\n // Atualiza o preço do componente\r\n ProductPurchase.updatePrice(currentProduct, variants[0], variantInventory);\r\n\r\n // Atualiza as últimas quantidades disponíveis\r\n ProductPurchase.setLastUnits(currentProduct, variants[0], variantInventory);\r\n }\r\n\r\n } else if (variants.length === 0) {\r\n // Produto não possui variantes, define como indisponível\r\n return ProductPurchase.setUnavailable(currentProduct);\r\n }\r\n\r\n if (variants.length > 0) {\r\n const allAttr1 = [...currentProduct.querySelectorAll('[data-attribute=\"1\"] [data-attribute-value]')];\r\n const allAttr2 = [...currentProduct.querySelectorAll('[data-attribute=\"2\"] [data-attribute-value]')];\r\n const allAttr3 = [...currentProduct.querySelectorAll('[data-attribute=\"3\"] [data-attribute-value]')];\r\n\r\n // Prepara para caso o atributo 1 não esteja em uso, scout por outros\r\n let attrToCheck = { index: false, options: [] };\r\n\r\n if (allAttr3.length > 0) attrToCheck = { index: 'property3', options: allAttr3 };\r\n if (allAttr2.length > 0) attrToCheck = { index: 'property2', options: allAttr2 };\r\n if (allAttr1.length > 0) attrToCheck = { index: 'property1', options: allAttr1 };\r\n\r\n // Baseado na ordem dos atributos, busca por variantes válidas\r\n if (attrToCheck.options.length > 0) {\r\n for (let index = 0; index < attrToCheck.options.length; index++) {\r\n const attribute = attrToCheck.options[index];\r\n const value = attribute.getAttribute('data-attribute-value');\r\n const availableVariants = ProductPurchase.productVariants[`${productId}`].filter((variant) => {\r\n\r\n // Venda por Locais\r\n // Busca informações da variante de acordo com o local selecionado\r\n let variantInventory = null;\r\n if (window.currentLocal) {\r\n variantInventory = variant.inventories.find(inventory => {\r\n return inventory.place && inventory.place.id && inventory.place.id === window.currentLocal.id;\r\n });\r\n } else if (ProductPurchase.useLocals) {\r\n // Variante com estoque indisponível, sem local selecionado, porém com estoque em algum dos locais\r\n variantInventory = variant.inventories.find(inventory => {\r\n return inventory.available;\r\n });\r\n }\r\n\r\n return variant.properties[attrToCheck.index] &&\r\n variant.properties[attrToCheck.index].value &&\r\n variant.properties[attrToCheck.index].value == value &&\r\n (\r\n (variant.available && !variantInventory) || // variante disponível sem local\r\n (variant.available && variantInventory && variantInventory.available) || // variante disponível com local disponível\r\n (!variant.available && variantInventory && variantInventory.available) // variante indisponível mas com local disponível\r\n );\r\n\r\n });\r\n\r\n if (availableVariants.length > 0) {\r\n attribute.classList.add('-available');\r\n } else {\r\n // O produto não tem variantes disponíveis\r\n attribute.classList.add('-unavailable');\r\n }\r\n }\r\n\r\n // Marca os atributos da primeira variante disponível,\r\n //com base na ordem que os atributos se apresentam na tela\r\n let hasFirstAvailable = false;\r\n\r\n for (const attribute of attrToCheck.options) {\r\n if (attribute.classList.contains('-available')) {\r\n attribute.click();\r\n hasFirstAvailable = true;\r\n\r\n if (attrToCheck.index == 'property1') {\r\n for (const attr2 of allAttr2) {\r\n if (attr2.classList.contains('-available')) {\r\n attr2.click();\r\n break;\r\n }\r\n }\r\n\r\n for (const attr3 of allAttr3) {\r\n if (attr3.classList.contains('-available')) {\r\n attr3.click();\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (attrToCheck.index == 'property2') {\r\n for (const attr3 of allAttr3) {\r\n if (attr3.classList.contains('-available')) {\r\n attr3.click();\r\n break;\r\n }\r\n }\r\n }\r\n\r\n break;\r\n }\r\n }\r\n\r\n // Quando não há nenhuma first variant com estoque, marca a primeira\r\n //opção indisponível, para exibir como indisponível\r\n if (!hasFirstAvailable) {\r\n attrToCheck.options[0].click();\r\n if (attrToCheck.index == 'property1') {\r\n if (allAttr2.length > 0) allAttr2[0].click();\r\n if (allAttr3.length > 0) allAttr3[0].click();\r\n }\r\n\r\n if (attrToCheck.index == 'property2') {\r\n if (allAttr3.length > 0) allAttr3[0].click();\r\n }\r\n }\r\n }\r\n }\r\n },\r\n\r\n // Configura a mesagem de ultimas unidades disponíveis\r\n setLastUnits: function (currentProduct, variant, inventory) {\r\n const lastUnitsWrapper = currentProduct.querySelector('.last-units');\r\n const availableQuantity = inventory ? inventory.available_quantity : variant.available_quantity;\r\n\r\n if (availableQuantity <= 5) {\r\n if (!availableQuantity) {\r\n lastUnitsWrapper.innerHTML = '';\r\n lastUnitsWrapper.classList.remove('-visible');\r\n } else if (availableQuantity > 1) {\r\n lastUnitsWrapper.innerHTML = `Últimas unidades`;\r\n lastUnitsWrapper.classList.add('-visible');\r\n } else {\r\n lastUnitsWrapper.innerHTML = 'Últimas unidades';\r\n lastUnitsWrapper.classList.add('-visible');\r\n }\r\n } else {\r\n lastUnitsWrapper.innerHTML = '';\r\n lastUnitsWrapper.classList.remove('-visible');\r\n }\r\n },\r\n\r\n // Configura o seletor de quantidade e suas mensagens\r\n setQuantitySelector: function (currentProduct, blockProduct) {\r\n const error = currentProduct.querySelector('.msg-response .msg-error');\r\n const buttonPlus = currentProduct.querySelector('[data-qtd-plus]');\r\n const buttonMinus = currentProduct.querySelector('[data-qtd-minus]');\r\n const input = currentProduct.querySelector('[name=\"quantity\"]');\r\n\r\n if (input && blockProduct) {\r\n let blockInput = blockProduct.querySelector('input[name=\"quantity\"]');\r\n if (blockInput)\r\n setTimeout(() => {\r\n input.value = blockInput.value;\r\n input.valueAsNumber = blockInput.value;\r\n input.setAttribute('value', blockInput.value);\r\n }, 100);\r\n }\r\n\r\n if (buttonPlus != null && buttonMinus != null) {\r\n buttonPlus.addEventListener('click', () => {\r\n const current = Number(input.value) + 1;\r\n const availableQuantity = Number(input.dataset.availableQuantity);\r\n\r\n if (!availableQuantity) {\r\n error.innerHTML = 'Produto em falta no estoque';\r\n error.classList.add('-visible');\r\n } else if (current > availableQuantity) {\r\n // Se o produto atingiu a quantidade máxima em estoque mostra uma mensagem\r\n error.innerHTML = 'Quantidade máxima em estoque.';\r\n error.classList.add('-visible');\r\n } else {\r\n input.value = current;\r\n input.setAttribute('value', current);\r\n }\r\n });\r\n\r\n buttonMinus.addEventListener('click', () => {\r\n const current = Number(input.value) - 1;\r\n\r\n if (current > 0) {\r\n input.value = current;\r\n input.setAttribute('value', current);\r\n\r\n // Se está mostrando a mensagem de quantidade máxima, remove ela\r\n if (error.classList.contains('-visible')) {\r\n error.classList.remove('-visible');\r\n error.innerHTML = '';\r\n }\r\n }\r\n });\r\n }\r\n },\r\n\r\n // Trata dos seletores em dropdown para atributos e personalizações\r\n handleDropdowns: function(currentProduct) {\r\n const dropdowns = currentProduct.querySelectorAll('.prod-option.-dropdown')\r\n if (!dropdowns) return\r\n\r\n // Configura abre/fecha do dropdown conforme clique nas opções\r\n return dropdowns.forEach(dropdown => {\r\n const dropAttrs = dropdown.querySelectorAll('[data-attribute-value], [data-customization] + label');\r\n dropdown.querySelector('.inner').classList.remove('-choosing')\r\n\r\n dropAttrs.forEach(attr => {\r\n attr.addEventListener('click', () => {\r\n attr.closest('.inner').classList.toggle('-choosing')\r\n\r\n // Garante que os outros dropdowns fechem quando clica em um novo\r\n dropdowns.forEach(checkDrop => {\r\n if (checkDrop === dropdown) return\r\n checkDrop.querySelector('.inner').classList.remove('-choosing')\r\n })\r\n });\r\n });\r\n })\r\n },\r\n\r\n // Envia o formulário de compra\r\n submitForm: function (currentProduct) {\r\n const { useLocals } = ProductPurchase;\r\n\r\n currentProduct.addEventListener('submit', (event) => {\r\n event.preventDefault();\r\n\r\n const groupShop = currentProduct.closest('[data-product-box]').getAttribute('data-prod-group-shop');\r\n\r\n // Venda por Locais\r\n if (useLocals && (window.currentLocal == null || !sessionStorage.getItem('local-cep'))) {\r\n // Caso não tenha local selecionado, abre o popup de inserção do CEP\r\n const localPopupOpener = document.querySelector('[data-show-locals-popup]');\r\n localPopupOpener && localPopupOpener.click();\r\n\r\n } else if (groupShop == null) {\r\n // Adição normal de produto - Compre Junto é controlado em outro componente\r\n const form = currentProduct;\r\n const parent = form.closest('[data-product-box]');\r\n\r\n const respValidated = Store.validateFormProduct(form);\r\n const boxResponse = parent.querySelector('.msg-response');\r\n\r\n if (respValidated.validated) {\r\n Store.addProduct(form, parent);\r\n } else {\r\n //console.info('não foi');\r\n Store.setRespValidateProduct(respValidated, form, boxResponse);\r\n }\r\n }\r\n });\r\n },\r\n\r\n // Funções de controle do formulário de compra\r\n handlePurchase: function (product, block) {\r\n const { checkCombinations, checkSelection, markFirstVariant, submitForm, setQuantitySelector, handleDropdowns } = ProductPurchase;\r\n\r\n const purchaseForm = product.querySelector(\"[data-product-purchase]\");\r\n\r\n if (purchaseForm && purchaseForm.getAttribute('data-processed') == 'false') {\r\n const attrOptions = purchaseForm.querySelectorAll('[data-attribute-value]');\r\n const attrInputs = purchaseForm.querySelectorAll('[data-prod-option] input');\r\n\r\n // Remarca demais atributos ao clicar em uma opção\r\n attrOptions.forEach((attr) => {\r\n attr.addEventListener('click', () => {\r\n checkCombinations(purchaseForm, attr);\r\n });\r\n });\r\n\r\n // Verifica variante para combinação de atributos selecionados\r\n attrInputs.forEach((input) => {\r\n input.addEventListener('change', () => {\r\n checkSelection(purchaseForm);\r\n });\r\n });\r\n\r\n setQuantitySelector(purchaseForm, block);\r\n markFirstVariant(purchaseForm);\r\n submitForm(purchaseForm);\r\n handleDropdowns(purchaseForm)\r\n purchaseForm.setAttribute('data-processed', true);\r\n\r\n }\r\n },\r\n\r\n // Retorna o HTML necessário para a compra rápida - Popup ou Formulário\r\n fetchQuickview: async function (id, type) {\r\n if (!id || !window.ProductPurchase) return\r\n\r\n try {\r\n const baseUrl = window.location.origin;\r\n const url = new URL(`/produto/quickview/${id}`, baseUrl);\r\n\r\n if (type == 'popup') url.searchParams.set('popup_quickview', true);\r\n if (type == 'group-shop') url.searchParams.set('group_shop', true);\r\n\r\n const response = await fetch(url);\r\n const data = await response.text();\r\n\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(data, 'text/html');\r\n const script = doc.querySelector('[data-product-variants]');\r\n\r\n // Popula o array de variantes\r\n const variants = JSON.parse(script.innerText);\r\n window.ProductPurchase.productVariants[`${id}`] = variants;\r\n\r\n // Retorna o formulário de compra ou o popup de compra rápida\r\n const purchaseEl = doc.querySelector('body').firstElementChild;\r\n return purchaseEl;\r\n\r\n } catch (error) { console.error(error) }\r\n },\r\n\r\n // Popup de compra rápida\r\n popupQuickview: {\r\n // Instancia o popup no DOM\r\n createPopup: async function (id, type) {\r\n const { fetchQuickview, handlePurchase, popupQuickview } = ProductPurchase;\r\n\r\n try {\r\n const purchaseEl = await fetchQuickview(id, type);\r\n const moreEl = document.querySelector(`.product-more [data-product-box=\"${id}\"]`);\r\n\r\n purchaseEl.setAttribute(\"data-popup-quickview\", id);\r\n purchaseEl.classList.add('-active');\r\n document.body.appendChild(purchaseEl);\r\n\r\n handlePurchase(purchaseEl, moreEl);\r\n\r\n window.Vnda.Component.Price.update();\r\n window.lazyLoad && window.lazyLoad.update();\r\n\r\n popupQuickview.close(purchaseEl);\r\n\r\n } catch (error) {\r\n console.error('Erro ao processar o popup de compra rápida do produto:', error);\r\n }\r\n\r\n },\r\n\r\n // Controla os botões de fechar o popup\r\n close: function (popup) {\r\n const closeButtons = popup.querySelectorAll('[data-close-popup-quickview]');\r\n\r\n closeButtons.forEach((button) => {\r\n if (button.getAttribute('data-processed') == 'false') {\r\n button.addEventListener('click', () => {\r\n popup.classList.remove('-active');\r\n });\r\n button.setAttribute('data-processed', true);\r\n }\r\n });\r\n },\r\n },\r\n\r\n // Popup Quickview - abertura ou criação\r\n handleQuickviewPopup: function (product, id, type) {\r\n const { popupQuickview } = ProductPurchase;\r\n const openPopupPurchaseButton = product.querySelector('[data-open-popup-quickview]');\r\n\r\n openPopupPurchaseButton && openPopupPurchaseButton.addEventListener('click', () => {\r\n if (!openPopupPurchaseButton.classList.contains(\"-searching\")) {\r\n openPopupPurchaseButton.classList.add('-searching')\r\n\r\n const popup = document.querySelector(`[data-popup-quickview='${id}']`);\r\n\r\n popup\r\n ? popup.classList.add(\"-active\")\r\n : popupQuickview.createPopup(id, type);\r\n\r\n setTimeout(() => openPopupPurchaseButton.classList.remove('-searching'), 500)\r\n }\r\n\r\n });\r\n },\r\n\r\n // Formulário Quickview - fetch e inserção do elemento\r\n handleQuickviewForm: async function (product, id, type) {\r\n const { fetchQuickview, handlePurchase } = ProductPurchase;\r\n\r\n const alreadyProcessed = product.getAttribute(\"data-quickview-processed\");\r\n if (!alreadyProcessed) {\r\n\r\n try {\r\n const purchaseEl = await fetchQuickview(id, type);\r\n\r\n if (!purchaseEl) {\r\n console.error(\"Erro ao carregar o formulário: purchaseEl vazio\")\r\n return;\r\n }\r\n\r\n product.appendChild(purchaseEl);\r\n handlePurchase(product);\r\n\r\n product.setAttribute(\"data-quickview-processed\", true);\r\n\r\n } catch (error) {\r\n console.error('Erro ao processar o formulário do produto:', error);\r\n }\r\n }\r\n },\r\n\r\n // Define o modelo de compra rápida - Popup / Formulário\r\n setQuickviewType: async function (product, id) {\r\n const { handleQuickviewPopup, handleQuickviewForm } = ProductPurchase;\r\n\r\n if (!product.hasAttribute(\"data-quickview-type\")) return;\r\n\r\n const quickviewType = product.getAttribute(\"data-quickview-type\");\r\n\r\n if (quickviewType == \"popup\") {\r\n handleQuickviewPopup(product, id, quickviewType)\r\n\r\n } else if (quickviewType == 'hover' && window.mobile == false) {\r\n let hoverTimeout;\r\n\r\n // Executa o fetch após 250ms no hover\r\n product.addEventListener(\"mouseenter\", () => {\r\n hoverTimeout = setTimeout(() => {\r\n handleQuickviewForm(product, id, quickviewType)\r\n }, 250);\r\n })\r\n\r\n // Cancela o temporizador ao sair do hover antes do tempo esperado pelo setTimeout\r\n product.addEventListener(\"mouseleave\", () => {\r\n clearTimeout(hoverTimeout);\r\n });\r\n\r\n } else if ((quickviewType == 'hover' && window.mobile) || 'group-shop') {\r\n handleQuickviewForm(product, id, quickviewType)\r\n }\r\n\r\n },\r\n\r\n // Observa os produtos em tela\r\n observeProducts: function (product) {\r\n const { setQuickviewType } = ProductPurchase;\r\n\r\n const observer = new IntersectionObserver(async (entries, observer) => {\r\n if (entries[0].isIntersecting) {\r\n const product = entries[0].target;\r\n const id = product.getAttribute(\"data-product-box\");\r\n product.setAttribute(\"data-quickview-ready\", true);\r\n\r\n setQuickviewType(product, id);\r\n observer.disconnect();\r\n }\r\n });\r\n\r\n observer.observe(product);\r\n },\r\n\r\n init: function (update) {\r\n const triggerUpdate = update || false;\r\n\r\n if (triggerUpdate) {\r\n this.products = document.querySelectorAll('[data-product-box]');\r\n this.productVariants = productVariants;\r\n }\r\n\r\n window.ProductPurchase = ProductPurchase;\r\n\r\n const { products, handlePurchase, observeProducts } = this;\r\n\r\n if (products.length > 0)\r\n products.forEach((product) => {\r\n\r\n if (product.querySelector(\"[data-product-purchase]\")) {\r\n handlePurchase(product);\r\n } else if (!product.getAttribute('data-quickview-ready')) {\r\n observeProducts(product);\r\n }\r\n\r\n });\r\n },\r\n};\r\n\r\nProductPurchase.init()\r\n"],"names":[],"sourceRoot":""}