Help
RSS
API
Feed
Maltego
Contact
Domain > apelsin.savemenu.ru
×
Welcome!
Right click nodes and scroll the mouse to navigate the graph.
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2020-12-21
52.85.79.55
(
ClassC
)
2020-12-21
52.85.79.89
(
ClassC
)
2024-06-30
18.161.6.57
(
ClassC
)
Port 80
HTTP/1.1 301 Moved PermanentlyServer: CloudFrontDate: Sun, 30 Jun 2024 08:05:56 GMTContent-Type: text/htmlContent-Length: 167Connection: keep-aliveLocation: https://apelsin.savemenu.ru/X-Cache: Redirect from cloudfrontVia: 1.1 1cbc126937aab64e42a05f9bf2f8daee.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P1X-Amz-Cf-Id: lasvZxrUeKDEPYnD2YCSqYvae-np4XSu6_dghHlMpdbYghhFYjKz8w html>head>title>301 Moved Permanently/title>/head>body>center>h1>301 Moved Permanently/h1>/center>hr>center>CloudFront/center>/body>/html>
Port 443
HTTP/1.1 200 OKContent-Type: text/htmlContent-Length: 100070Connection: keep-aliveVary: Accept-Encodingx-amz-id-2: rJWH44Abwvu0OJPFb2JJnmJgU/oGqcjeDQ+tWI21pAUy+VMfuFzoin4xkF33TziyjIg31iL01UYx-amz-request-id: 88VMCSYWGEWY0JNEDate: Sun, 30 Jun 2024 08:05:58 GMTLast-Modified: Tue, 13 Oct 2020 11:14:53 GMTx-amz-version-id: clrzLRUyHY0SRRrmgGgPTHB3j5BpTlAHETag: 6d4186a6d6f40fd3bd500641e676e62fServer: AmazonS3X-Cache: Miss from cloudfrontVia: 1.1 6af36c6902a46beec743522a9bbb3ab0.cloudfront.net (CloudFront)X-Amz-Cf-Pop: HIO52-P1X-Amz-Cf-Id: DbiN91pkWvw6CTEqxaW3mWaih5lR8cK6mO3KVrjEQeJU-fabO3qWAA !DOCTYPE html> html> head> title>Apelsin RK/title> meta propertyog:url contenthttps://apelsin.savemenu.ru /> meta propertyog:type contentrestaurant.restaurant /> meta propertyog:title contentApelsin RK /> meta propertyog:description contentСвежее меню здесь! /> meta propertyog:image content./img/icon-512x512.png /> meta charsetutf-8 /> meta http-equivX-UA-Compatible contentIEedge> meta http-equivcleartype contenton> meta nameMobileOptimized content320> meta nameHandheldFriendly contentTrue> meta nameapple-mobile-web-app-capable contentyes> meta nameviewport contentwidthdevice-width, initial-scale1.0, user-scalableno> meta nametheme-color content#f0efed /> link relpreload href./img/9716903544326500.png asimage> link relmanifest href./manifest.json> link relapple-touch-icon sizes192x192 href./img/icon-192x192.png /> link relstylesheet hrefhttps://unpkg.com/buefy/dist/buefy.min.css> link relstylesheet typetext/css mediascreen hrefhttps://savemenu.ru/_public/css/styles.min.css /> link hrefhttps://unpkg.com/basscss@8.0.2/css/basscss.min.css relstylesheet> link relstylesheet typetext/css mediascreen hrefhttps://savemenu.ru/_public/css/styles.css /> link hrefhttps://fonts.googleapis.com/css?familyIBM+Plex+Sans:300,400,600|Montserrat&subsetcyrillic relstylesheet> link hrefhttps://fonts.googleapis.com/css?familyCaveat:400,700|Comfortaa:400,600,700|Neucha|Prosto+One|Roboto+Slab:300,400,600&displayswap&subsetcyrillic relstylesheet> style> body { background-color: #adb0b5; } #content { background-color: #3a3a3a; } .background { background-image: url(https://savemenu.ru/_public/img/bg-dark.png) !important; } .Header h3, .Header p { color: #ededed; font-family: Roboto Slab, serif; } .information p, .information h4, .information a { color: #fff; } .price::after { color: inherit; } .menu .desc, .menu .price, .menu .price-plain { color: #626060; } .menu .itemTags, .menu .priceComment { color: #555353bd; } .menu .item:hover { box-shadow: inset 0px 0px 14px -7px #868686; } .cart .price, .cart-items .price { font-size: 13px; border-radius: 6px; cursor: pointer; text-align: center; color: #595958; margin-bottom: 5px; margin-left: auto; max-width: 60px; box-shadow: 2px 2px 3px #686868a3, -3px -3px 5px #fff; background-color: #eee; } #cartStatusBar { border-top: 8px solid #80808029; background: #e4e3e1!important; color: rgb(34, 34, 34)!important; } #cartButtonBar { border-top: 8px solid #80808029; background: rgb(234, 234, 234)!important; } .menu .item { border-bottom: #d5d5d5 1px solid; background: #eee; } .itemsBlock { box-shadow: 5px 5px 12px #131313, -5px -5px 3px #c8c8c81a; } .item .image { box-shadow: 3px 3px 3px #686868a3, -3px -3px 5px #fff; border-radius: 10px; } .item-has-image { box-shadow: 1px 1px 1px #68686880, -1px -1px 5px #fff; border-radius: 4px; } .input-number-decrement, .input-number-increment { background-color: #eee!important; } .price.inCart, .cart-items .price { border: #ccc9c9 inset 2px !important; background-color: #b3b3b1; font-weight: bold; color: white; box-shadow: none; margin-bottom: 1px; } /style> style>/style> style> .expand-enter-active,.expand-leave-active { transition: height 0.1s linear; overflow: hidden;}.expand-enter,.expand-leave-to { height: 20.9px;}.animation,.toggle-card { will-change: height; transform: translateZ(0); backface-visibility: hidden; perspective: 1000px;}.itemImage { height: 250px;}.title { font-size: 22px;}.input-number-group { display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center;}.input-number-group inputtypenumber::-webkit-inner-spin-button,.input-number-group inputtypenumber::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none;}.input-number-group .input-group-button {}.input-number-group .input-number { border-bottom: 1px solid #dde0e1 !important; border-top: 1px solid #dde0e1 !important; width: 30px; padding: 0 6px; vertical-align: top; text-align: center; outline: none; display: block; margin: 0;}.input-number-group .input-number,.input-number-group .input-number-decrement,.input-number-group .input-number-increment { border: none; height: 25px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border-radius: 0;}.input-number-group .input-number-decrement,.input-number-group .input-number-increment { display: inline-block; width: 30px; background: #ede4cb; font-size: 22px; color: #0a0a0a; text-align: center; font-weight: bold; cursor: pointer; font-weight: 400;}.input-number-group .input-number-decrement { border-bottom-left-radius: 6px; border-top-left-radius: 6px;}.input-number-group .input-number-increment { border-bottom-right-radius: 6px; border-top-right-radius: 6px;}.input-number-group { justify-content: space-evenly;}.price.inCart { border: #b0aeae dotted 2px;}.cart-items .price { max-width: 90px;}.fixed-bottom { position: fixed; bottom: 0; padding-bottom: 11px;}.sticky-bottom { position: sticky; bottom: 0; padding-bottom: 40px;}.dialog .modal-card { min-width: 450px; text-align: center;}.dialog .modal-card .modal-card-foot { justify-content: center;}.modal-card-foot,.modal-card-head { background-color: #fff;}.modal-card-head { border-bottom: none;}.modal-card-foot { border-bottom: none;}.media .media-content { text-align: center;}#content, .phone { margin-bottom: 0;}.name { color: #403f3f; }.input:focus, .input:hover { border: 1px solid #d9d7d7 !important; background-color: white !important;}.search input { border: none; box-shadow: none!important; transition: none;}.referral a { color: #0000008c;}.navbar { background: #f0efed; } .slideMenu span { background-color: #999595; } .navbar svg { color: #1f8bea; } .desc a { color: #177ad0; text-decoration: underline;}.expanded { height:auto!important;}.note { background-color: #ddf0dd; width: max-content; padding: 3px 10px; border-radius: 5px; max-width: 100%;}.input::placeholder, .select select::placeholder, .taginput .taginput-container.is-focusable::placeholder, .textarea::placeholder { color: rgba(54, 54, 54, 0.6); font-size: 14px;} /style> /head> body> script srchttps://cdn.jsdelivr.net/npm/vue/dist/vue.js>/script> script srchttps://browser.sentry-cdn.com/5.22.3/bundle.min.js integritysha384-A1qzcXXJWl+bzYr+r8AdFzSaLbdcbYRFmG37MEDKr4EYjtraUyoZ6UiMw31jHcV9 crossoriginanonymous>/script> script srchttps://browser.sentry-cdn.com/5.22.3/vue.min.js crossoriginanonymous>/script> script srchttps://unpkg.com/buefy/dist/buefy.min.js>/script> script srchttps://savemenu.ru/_public/js/vue-carousel.min.js>/script> script srchttps://savemenu.ru/_public/js/sidenav.min.js>/script> script srchttps://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js>/script> script srchttps://unpkg.com/axios/dist/axios.min.js>/script> script srchttps://cdnjs.cloudflare.com/ajax/libs/is_js/0.9.0/is.min.js integritysha512-DvhVUdQWYI9UoF5HGHhl00nbUFcr+j6dGlg/FSrolqR3EridE8CF82nCNAZsE4iAPkw/ws0O7IrZ1jOUuJQXxg crossoriginanonymous>/script> script srchttps://kassa.yandex.ru/checkout-ui/v2.js>/script> script typetext/javascript srchttps://maps.googleapis.com/maps/api/js?keyAIzaSyCX7ocKAW9fiQT39PXvEsqcVwYgoKP27wM&librariesplaces>/script> script srchttps://unpkg.com/vue-tel-input>/script> script> Sentry.init({ dsn: https://bba47234985d48268eb851fba1627a20@o386692.ingest.sentry.io/5221245, integrations: new Sentry.Integrations.Vue({Vue, attachProps: true, logErrors: true}), }); /script> div idapp> b-loading :is-full-pagetrue :active.syncisLoading :can-cancelfalse>/b-loading> div classphone> div idbackdrop> /div> div idsidenav classbackground stylevisibility:hidden;> div classheader stylebackground: url(./img/background.png) center center no-repeat> div classclearfix is-vcentered> div classcol col-4> img classlogo src./img/icon-512x512.png alt> /div> /div> /div> div classinformation> h4>Apelsin RK/h4> p>Нарвская ул., 21, Москва, Россия, 125212/p> p> Корпоративное кафе для сотрудников Компании Русклимат/p> a hreftel:+74957771967 доб. 1580 onclickmixpanel.track(Phone number clicked)>svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-phone> path dM22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z> /path> /svg> +74957771967 доб. 1580/a> pre stylebackground-color: inherit; border: none; font-family: inherit; font-size: inherit; line-height: inherit;> /pre> /div> /div> div idcontent classbackground bg-color> nav classnavbar nav-desktop styleopacity: 0.93; display: block;> div class stylepadding: 0 10px> div classclearfix> div classcol col-2> div idmenu-toggle classslideMenu> span>/span> span>/span> span>/span> /div> /div> div classcol col-8> div classsearch> svg v-ifsearchQuery.length > 1 @clicksearchQuery; searchingfalse classsearch-right-addon xmlnshttp://www.w3.org/2000/svg width18 height18 viewBox0 0 24 18 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-x>line x118 y16 x26 y218>/line>line x16 y16 x218 y218>/line>/svg> input classinput stylemargin-top: 8px;border-radius: 20px; typetext placeholderПоиск v-modelsearchQuery @focussearching!searching @inputsearchingfalse> div v-ifsearching && tagList && tagList0 classsearch-tag-bar> span v-fortag in tagList @clicksearchQuery tag;searchingfalse;> #{{tag}} /span> /div> /div> /div> div classcol col-2 text-right no-padding> div :key1 v-if(!allExpanded) @clickexpandToggle(true) classnavButton> svg stylemargin-top:14px; xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-maximize-2>polyline points15 3 21 3 21 9>/polyline>polyline points9 21 3 21 3 15>/polyline>line x121 y13 x214 y210>/line>line x13 y121 x210 y214>/line>/svg> /div> div :key2 v-else @clickexpandToggle(false) classnavButton> svg stylemargin-top:14px; xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-minimize-2>polyline points4 14 10 14 10 20>/polyline>polyline points20 10 14 10 14 4>/polyline>line x114 y110 x221 y23>/line>line x13 y121 x210 y214>/line>/svg> /div> /div> /div> /div> div idprogressBar stylewidth:100%> div idprogress styleheight:2px; background-color:rgba(0, 188, 212, 0.5); margin-top:-13px; :styleprogress>/div> /div> /nav> div classmenu cart stylemin-height: 99vh;> div classclearfix> div classcol col-12 no-padding> div class> !-- itemsBlock --> div v-for(item, index) in menu> div v-if!item.isHidden> component v-on:header-clickcollapsSection v-on:add-to-cartaddToCart v-if!item.hidden v-bind:isblocksitem.itemType.component v-bind:itemitem v-bind:indexindex v-bind:classesgetClasses(item) > /component> div v-ifitem.subitems classitemsBlock> transition-group appear namestaggered-fade tagdiv v-bind:cssfalse v-on:before-enterbeforeEnter v-on:enterenter v-on:leaveleave > component v-for(subitem, index2) in item.subitems v-if!subitem.isHidden && item.expanded :keysubitem.itemOrder v-on:add-to-cartaddToCart v-bind:itemsubitem v-bind:isblockssubitem.itemType.component v-bind:classesgetClasses(subitem) > /component> /transition-group> /div> /div> /div> /div> /div> /div> /div> div v-ifObject.keys(cart).length ! 0 || showCart || orderCompleted idcartStatusBar :class{fixed-bottom: showCart, sticky-bottom: !showCart} stylewidth: 100%;max-width: 700px; padding-top: 15px; @clickshowCart!showCart; $forceUpdate()> div classcol col-6 styletext-align:left;> svg xmlnshttp://www.w3.org/2000/svg width24 height24 stylevertical-align: middle; viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-shopping-cart>circle cx9 cy21 r1>/circle>circle cx20 cy21 r1>/circle>path dM1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6>/path>/svg> span v-if!orderCompleted stylevertical-align: middle;margin-left: 0.5rem;font-weight: 600;>{{cartTotal()}} {{currency}}/span> span v-else stylevertical-align: middle;margin-left: 0.5rem;font-weight: 600;>Заказано/span> /div> div v-ifshowCart classcol col-6 styletext-align:right;> svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-chevron-down>polyline points6 9 12 15 18 9>/polyline>/svg> /div> div v-else classcol col-6 styletext-align:right;> svg xmlnshttp://www.w3.org/2000/svg width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-chevron-up>polyline points18 15 12 9 6 15>/polyline>/svg> /div> /div> div v-ifshowCart classfixed top-0 stylebackground: white;width: 100%;max-width: 700px; height:calc(100% - 54px); z-index:10; overflow:auto;> cart v-bind:itemscart v-bind:orderingordering v-bind:currencycurrency v-bind:completedorderCompleted @order-placedclearQty(all); orderCompleted true; @change-delivery-optionoption > changeDelivery(option) > /cart> /div> /div> /div> /div> script> var blocks { item: { component: { props: item, classes, name: item, data() { return { expanded: false, animationDone: true, } }, template: ` div :iditem.itemId v-bind:classclasses @clickopenCard()> div classclearfix> div v-ifitem.image ! 0 classcol col-2 stylemax-height:1rem;> div classimage v-bind:style{ backgroundImage: url( + getIcon(item.image) + )} > /div> /div> div :class{col col-10: item.image !0} stylepadding:0> div classclearfix> div classcol col-9 :class{no-padding: item.image !0} stylepadding-right: 0;> div classname v-bind:class{ nameExpanded: expanded }> {{item.itemName}} /div> div classunder-name > div v-ifitem.hasImage styledisplay:inline-block;> svg xmlnshttp://www.w3.org/2000/svg viewBox0 0 24 24 fillnone strokecurrentColor stroke-width1.5 stroke-linecapround stroke-linejoinround classfeather feather-image item-has-image >rect x3 y3 width18 height18 rx2 ry2>/rect>circle cx8.5 cy8.5 r1.5>/circle>polyline points21 15 16 10 5 21>/polyline>/svg> /div> div classitemTags v-ifitem.itemTags && item.itemTags.length ! 0> span v-fortag in item.itemTags>#{{tag}} /span> /div> div v-else> div classitemTags v-ifitem.image ! 0 && !item.hasImage && !item.itemTags && !item.itemPriceComment && item.itemDesc && item.itemDesc.length > 0> span>/span> /div> /div> /div> /div> div classcol col-3 styletext-align: right;padding-left: 0;> div classprice v-bind:class{inCart: item.qty > 0} @click.stoppriceClick(item)> {{item.itemPrice}} /div> div classpriceComment> {{item.itemPriceComment}} /div> /div> /div> /div> /div> div classclearfix v-if(item.itemDesc && item.itemDesc.length > 0) || item.hasImage> div classcol col-12 > div v-if!item.itemTags || !item.itemTags0 classcol col-3>/div> div key1 v-if!expanded && animationDone classdesc descShort> {{getShortString(item.itemDesc)}} span v-ifitem.itemDesc && item.itemDesc.length getShortString(item.itemDesc).length> ... /span> /div> transition nameexpand @enterenter @after-enter @leaveleave > div key2 v-ifexpanded classanimation> div classdesc> pre classno-padding no-margin>{{item.itemDesc}}/pre> /div> div v-ifitem.hasImage ! undefined && item.hasImage.length > 0 classitemImage v-bind:style{ backgroundImage: url( + getItemImage(item.hasImage0) + )} > /div> /div> /transition> /div> /div> /div> `, mounted() { if (this.item.expanded) { console.log(Expanding, this.item.itemName); this.expanded true; } }, methods: { getItemImage(img) { img img.toString(); if (img.startsWith(http://) || img.startsWith(https://)) return img else return ./img/ + img + .png }, priceClick(item) { if (!item.qty) { this.$set(item, qty, 1) item.itemPrice++; item.itemPrice--; item.itemPrice Math.round(item.itemPrice * 100) / 100 this.$forceUpdate(); } else { delete item.qty item.itemPrice++; item.itemPrice--; item.itemPrice Math.round(item.itemPrice * 100) / 100 this.$forceUpdate(); } this.$emit(add-to-cart, item) }, openCard: function() { this.expanded !this.expanded }, getShortString(str) { if (!str) return str str.toString(); let width document.documentElement.clientWidth let symbols width / 7 return str.substring(0,symbols).trim() }, getIcon(img) { let url ; if (img 0) url ; else if (img.includes(/)) url https://savemenu.ru/ + img; else url https://savemenu.ru/_public/icons/ + img + .png; return url; }, enter: function(element) { document.getElementById(this.item.itemId.toString()).style.height auto const width getComputedStyle(element).width; element.style.width width; element.style.position absolute; element.style.visibility hidden; element.style.height auto; const height getComputedStyle(element).height; element.style.width null; element.style.position null; element.style.visibility null; element.style.height 20.8px; getComputedStyle(element).height; setTimeout(() > { element.style.height height; element.style.marginTop 0; }); }, afterEnter(element) { element.style.height auto; }, leave(element, done) { this.animationDone false const height getComputedStyle(element).height; element.style.height height; getComputedStyle(element).height; setTimeout(() > { element.style.height 20.8px; setTimeout(() > { this.animationDone true done() },100) }); }, afterLeave(element) { this.animationDone true } } }}, Header: { component: { components: { carousel: VueCarousel.Carousel, slide: VueCarousel.Slide }, props: index, item, classes, name: Header, template: ` div :iditem.itemId v-bind:classclasses> div v-on:click$emit(header-click, index, item.subitems)> h3 classtitle> span v-ifitem.subitems && !item.expanded classexpand-trigger> svg xmlnshttp://www.w3.org/2000/svg width18 height18 viewBox0 0 24 18 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-chevron-right>polyline points9 18 15 12 9 6>/polyline>/svg> /span> span v-else-ifitem.subitems && item.expanded classexpand-trigger> svg xmlnshttp://www.w3.org/2000/svg width18 height18 viewBox0 0 24 18 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-chevron-down>polyline points6 9 12 15 18 9>/polyline>/svg> /span> {{item.itemName}}/h3> p stylemargin-bottom:5px>{{item.itemDesc}}/p> div v-ifitem.hasImage && item.hasImage0 classimg headerSeparator v-bind:style{ backgroundImage: url( + getimageUrl(item.hasImage0) + )} > /div> /div> div classimageBlock v-ifitem.catSlider && item.expanded && getSectionImages(item.subitems).length > 0> carousel :perPage1 :navigationEnabledtrue :paginationEnabledfalse :autoplaytrue :looptrue :paginationSize6 paginationPositionbottom-overlay> slide v-for(image, i) in getSectionImages(item.subitems) :keyi> div classitemImage v-bind:style{ backgroundImage: url(./img/ + image + .png)} stylemargin-left:0;border-radius: 7px; > /div> /slide> /carousel> /div> /div> `, methods: { getSectionImages: function(subitems) { let images for (i in subitems) { if (subitemsi.itemType item && subitemsi.hasImage) images.push(subitemsi.hasImage0) } return images }, getimageUrl(img) { if (!img) return img img.toString() if (img.includes(ctlg_)) return https://savemenu.ru/_public/img/el/ + img.split(ctlg_)1 + .png else return img/ + img + .png }, } } }, pushSubscribeButton: { component: { components: { carousel: VueCarousel.Carousel, slide: VueCarousel.Slide }, props: item, classes, name: pushSubscribeButton, template: ` carousel :perPage1 :navigationEnabledfalse> slide> div styleborder-radius: 10px; cursor: default;> div :iditem.itemId v-bind:classclasses> div classclearfix> div classcol col-7 stylepadding-right: 0;> div classname> {{item.itemName}} /div> /div> div classcol col-5> a classbutton subcribeToPushBtn onclicksubscribeToPush()>{{item.itemPrice}}/a> /div> /div> div classclearfix> div classcol col-12> div classdesc> {{item.itemDesc}} /div> /div> /div> /div> /div> /slide> /carousel> ` } }, infoBlock: { component: { props: item, classes, name: infoBlock, data() { return { expanded: false, animationDone: true, } }, template: ` div :iditem.itemId v-bind:classclasses @clickopenCard()> div v-ifitem.hasImage ! undefined && item.hasImage.length > 0> div v-ifitem.hasImage ! undefined && item.hasImage.length > 0 classitemBlockImage v-bind:style{ backgroundImage: url(./img/ + item.hasImage0 + .png)} > /div> /div> div classmt-1 stylepadding-left:0.5rem;> div classname v-bind:class{ nameExpanded: expanded } stylemargin-top:1rem;> {{item.itemName}} /div> div key1 v-if!expanded && animationDone classdesc descShort v-htmlgetShortString(item.itemDesc)> span v-ifitem.itemDesc && item.itemDesc.length getShortString(item.itemDesc).length> ... /span> /div> transition nameexpand @enterenter @after-enter @leaveleave > div key2 v-ifexpanded classanimation> div classdesc> pre v-htmlitem.itemDesc>/pre> /div> /div> /transition> /div> /div> `, methods: { openCard: function() { this.expanded !this.expanded }, getShortString(str) { if (!str) return str str.toString(); let width document.documentElement.clientWidth let symbols width / 7 return str.substring(0,symbols).trim() }, enter: function(element) { document.getElementById(this.item.itemId.toString()).style.height auto const width getComputedStyle(element).width; element.style.width width; element.style.position absolute; element.style.visibility hidden; element.style.height auto; console.log(element); const height getComputedStyle(element).height; element.style.width null; element.style.position null; element.style.visibility null; element.style.height 20.8px; getComputedStyle(element).height; setTimeout(() > { element.style.height height; element.style.marginTop 0; }); }, afterEnter(element) { element.style.height auto; }, leave(element, done) { this.animationDone false const height getComputedStyle(element).height; element.style.height height; getComputedStyle(element).height; setTimeout(() > { element.style.height 20.8px; setTimeout(() > { this.animationDone true done() },100) }); }, afterLeave(element) { this.animationDone true } } } }, imageBlock: { component: { components: { carousel: VueCarousel.Carousel, slide: VueCarousel.Slide }, props: item, classes, name: imageBlock, data() { return { slideNo: 0 } }, template: ` div v-ifitem.hasImage ! undefined && item.hasImage.length > 0 :iditem.itemId v-bind:classclasses> carousel :perPage1 :navigationEnabledtrue :autoplaytrue :paginationSize6 paginationPositionbottom-overlay> slide v-for(image, i) in item.hasImage :keyi> div v-bind:style{ backgroundImage: url( + getimageUrl(image) + )} classimg stylemargin-top: 0.5rem;border-radius:7px;background-position: center; background-size:contain;background-repeat:no-repeat;> /div> /slide> /carousel> /div> `, methods: { nextSlide() { this.slideNo++; }, getimageUrl(img) { if (!img) return img img.toString() if (img.includes(ctlg_)) return https://savemenu.ru/_public/img/el/ + img.split(ctlg_)1 + .png else return img/ + img + .png } } } }, cart: { component: { props: items, completed, ordering, currency, name: cart, data() { return { editing: false, loading: false, fields: {name: Имя, value: , type: text, required: true}, {name: Организация, value: , type: text, required: true}, {name: Телефон, value: , type: tel, required: true}, orderBtnActive: false, } }, template: ` div v-ifordering.active true idcart> div classheader p2> h1>Корзина/h1> /div> div classp2> b-notification v-ifcompleted typeis-success > Заказ успешно оформлен. /b-notification> /div> div classcart-items style> div v-for(item, index) in items v-bind:keyitem.itemId classitem> div classclearfix> div v-ifitem.image ! 0 classcol col-2 stylemax-height:1rem;> div classimage stylewidth: 30px;height: 30px;margin-right: 10px; v-bind:style{ backgroundImage: url( + getIcon(item.image) + )} > /div> /div> div :class{col col-10: item.image !0} stylepadding:0> div classclearfix> div classcol col-8 :class{no-padding: item.image !0} stylepadding-right: 0;> div classname> {{item.itemName}} /div> /div> div classcol col-4 styletext-align: right;padding-left: 0;> div v-if!item.editMode classprice stylefont-size:14px; margin-left:10px @clickeditCartItem(item)> {{item.qty}} x {{item.itemPrice}} /div> div v-else classqty-change styletext-align: left;padding-left: 0;> div classinput-group input-number-group> div classinput-group-button @clickchangeQty(index, -1)> span classinput-number-decrement>-/span> /div> input classinput-number typenumber value1 min0 max1000 v-modelitem.qty> div classinput-group-button @clickchangeQty(index, 1)> span classinput-number-increment>+/span> /div> /div> /div> /div> /div> /div> /div> /div> /div> hr /> div classtotal p2 styletext-align:right> h3>Всего: {{cartTotal()}} {{currency}}/h3> /div> div v-if!completed idinputFields classfields p2 stylemargin-bottom:70px;> div v-forfield, index in fields classp1 :keyindex> b-field label-positionon-border :labelfield.name> b-input sizeis-medium :requiredfield.required :typefield.type :validation-messagefield.valMsg?valMsg:* @focusscrollIntoView(index) :custom-classfield+index v-modelfield.value refinputFields>/b-input> /b-field> /div> /div> div v-if!completed idcartButtonBar classfixed stylepadding: 0.7rem;width: 100%;max-width: 700px; bottom: 54px;text-align: center;z-index: 100;> b-button :loadingloading classbutton is-cta :class{is-light : !orderBtnActive, is-cta: orderBtnActive} stylepadding-left: 50px;padding-right: 50px;border-radius: 16px; @clickplaceOrder()>Заказать/b-button> /div> /div> `, mounted() { if (this.ordering.user_fields) this.fields this.ordering.user_fields }, methods: { getIcon(img) { let url ; if (img 0) url ; else if (img.includes(/)) url https://savemenu.ru/ + img; else url https://savemenu.ru/_public/icons/ + img + .png; return url; }, cartTotal() { let total 0; for (let i0; i this.items.length; i++) { total total + parseFloat(this.itemsi.itemPrice) * this.itemsi.qty } return total }, changeQty(i, inc) { this.itemsi.qty this.itemsi.qty + inc; this.itemsi.itemPrice++; this.itemsi.itemPrice--; if (this.itemsi.qty 0) this.items.splice(i, 1); this.$forceUpdate(); }, editCartItem(item) { Vue.set(item,editMode,true) setTimeout(() > { item.editModefalse }, 2000) }, scrollIntoView(index){ let field document.getElementsByClassName(field+index)0 console.log(field); setTimeout(function() { field.scrollIntoView(); }, 100); }, placeOrder() { let validated false for (let i0; ithis.$refs.inputFields.length; i++) { if (this.$refs.inputFieldsi.checkHtml5Validity()) validated true else validated false } if (validated) { let data {} data.order this.items data.fields this.fields data.domain savemenu.ru, data.subdomain window.location.hostname, data.to this.ordering.email this.loading true axios.post(https://qc63hbjbvb.execute-api.us-east-1.amazonaws.com/dev/placeOrder, data) .then(()>{ this.$emit(order-placed) this.loading false } ) } else document.getElementById(inputFields).scrollIntoView(); } }, } },} var installPrompt; window.addEventListener(beforeinstallprompt, e > { installPrompt e; console.log(Stashed,installPrompt); }); new Vue({ el: #app, components: { carousel: VueCarousel.Carousel, slide: VueCarousel.Slide, }, data: { blocks: blocks, place: {}, itemsList: , tagList: , searchQuery: , searching: false, cart: , showCart: false, progress: { width: 0, transition-duration: 3s }, orderCompleted: false, ordering: {active:true,email:zakaz@apelsin.moscow,fields:{name:{title:Имя,hidden:false},email:{title:Email,hidden:false},phone:{title:Телефон,hidden:false}},payment:{active:true,integrations:yandexMoney,options:{type:yandexMoney,active:true,name:Оплата online,message:Совершите оплату в открывшемся окне}},delivery:{active:true,integrations:,options:{type:pickup,name:Заберу сам(а),cost:0,active:true,message:После оплаты, заказ можно забрать через 30 минут!}},finalMessage:Спасибо за заказ. Еда будет готова в течение 30 минут.}, currency: ₽, isLoading: false, deliveryCost: 0, }, computed: { menu() { if (!this.place.menu) return else if (this.searchQuery.length > 1) { let list this.itemsList.filter(item > { return item.search.toLowerCase().includes(this.searchQuery.toLowerCase()) }) let searchResults searchResults0 { itemId: searchHeader, itemName: Поиск:, itemType: Header, expanded: true, subitems: list } return searchResults } else return this.place.menu }, allExpanded() { for (item in this.menu) { if (this.menuitem.expanded) return true; } return false; }, }, methods: { changeDelivery(option) { console.log(option cost:, +option.cost) if (!option.cost || isNaN(+option.cost)) { this.deliveryCost 0 return } this.deliveryCost parseInt(option.cost) }, getClasses: function(item) { let classes item.itemType + if (item.itemType item && (!item.itemDesc || item.itemDesc || item.itemDesc || item.itemDesc \n)) classes classes + noDesc if (item.itemType Header && !item.subitems) classes classes + bigHeader if ((item.itemTags && item.itemTags0) || (item.itemPriceComment && item.itemPriceComment !) || item.hasImage) classes classes + hasUnderLine if (item.itemType item && item.image 0) classes classes + noIcon if (item.itemType imageBlock) if (!item.imgSize) classes classes + h-100 else classes classes + item.imgSize + if (item.hasImage && item.hasImage0 && item.hasImage0.toString().includes(ctlg)) classes + color-filter if (item.expanded) classes + expanded return classes }, collapsSection: function(index, subitems) { Vue.set(this.menuindex, expanded, !this.menuindex.expanded) }, expandToggle: function (state) { for (i in this.menu) { Vue.set(this.menui, expanded, state) } }, getSectionImages: function(subitems) { let images for (i in subitems) { if (subitemsi.hasImage) images.push(subitemsi.hasImage0) } console.log(images) return images }, beforeEnter: function (el) { el.style.opacity 0 el.style.height 0 }, enter: function (el, done) { var delay el.dataset.index * 1 let collapsedHeight 86px if (el.className.includes(h-)) collapsedHeight parseInt(el.className.substr(el.className.indexOf(h-)+2,3)) + 35 else if (el.className.includes(noDesc)) collapsedHeight 67px else if (!el.className.includes(hasUnderLine) && el.className.includes(noIcon)) collapsedHeight 67px else if (el.className.includes(infoBlock)) collapsedHeight 289px setTimeout(function () { Velocity( el, { opacity: 1, height: collapsedHeight }, { complete: done } ) }, delay) }, leave: function (el, done) { var delay el.dataset.index * 1 setTimeout(function () { Velocity( el, { opacity: 0, height: 0 }, { complete: done } ) }) }, addToCart: function (item) { if (this.ordering.active ! true && this.ordering.active ! true) return if (this.place.options.isDisabled) { this.$buefy.snackbar.open({ message: Приложение работает в пробном режиме, position: is-top, actionText: OK, indefinite: true }) return } if (this.orderCompleted) { this.orderCompleted false; this.cart.splice(0, this.cart.length); } let repeated false for (let j0; j this.cart.length; j++) { let i this.cartj if (i.itemId item.itemId) { repeated true this.cart.splice(j, 1) this.$forceUpdate(); break } } if (!repeated) { item.qty 1; this.cart.push(JSON.parse(JSON.stringify(item))) item.itemPrice++; item.itemPrice--; item.itemPrice Math.round(item.itemPrice * 100) / 100 } }, cartTotal() { let total 0; for (let i0; i this.cart.length; i++) { total total + parseFloat(this.carti.itemPrice) * this.carti.qty } total + this.deliveryCost return Math.round(total * 100) / 100 }, clearQty(id) { for (let i0; i this.place.menu.length; i++) { let item this.place.menui if (item.itemType ! item) continue if ((item.qty && item.itemIdid) || id all) { this.$set(item, qty, 0) item.itemPrice++; item.itemPrice--; } if (item.subitems) { for (let j0; jitem.subitems.length; j++) { if ((item.subitemsj.qty && item.subitemsj.itemIdid) || id all) this.$set(item.subitemsj, qty, 0) item.subitemsj.itemPrice++; item.subitemsj.itemPrice--; } } } this.$forceUpdate(); }, }, created() { let url https://grabmenu-users.s3.ap-south-1.amazonaws.com/apelsin/data.json; fetch(url) .then(response > response.json()) .then(response > { this.place response this.tagList getTags(response.menu) this.itemsList flattenList(response.menu); setTimeout(() > { this.progress { width: 0px, transition-duration: 0s } }) }) .catch(error > console.log(Failed because: + error)); }, mounted() { //!-- start Mixpanel --> (function(c,a){if(!a.__SV){var bwindow;try{var d,m,j,kb.location,fk.hash;dfunction(a,b){return(ma.match(RegExp(b+(^&*))))?m1:null};f&&d(f,state)&&(jJSON.parse(decodeURIComponent(d(f,state))),mpeditorj.action&&(b.sessionStorage.setItem(_mpcehash,f),history.replaceState(j.desiredHash||,c.title,k.pathname+k.search)))}catch(n){}var l,h;window.mixpanela;a._i;a.initfunction(b,d,g){function c(b,i){var ai.split(.);2a.length&&(bba0,ia1);bifunction(){b.push(i.concat(Array.prototype.slice.call(arguments, 0)))}}var ea;undefined!typeof g?eag:gmixpanel;e.peoplee.people||;e.toStringfunction(b){var amixpanel;mixpanel!g&&(a+.+g);b||(a+ (stub));return a};e.people.toStringfunction(){return e.toString(1)+.people (stub)};ldisable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove.split( ); for(h0;hl.length;h++)c(e,lh);var fset set_once union unset remove delete.split( );e.get_groupfunction(){function a(c){bcfunction(){call2_argsarguments;call2c.concat(Array.prototype.slice.call(call2_args,0));e.push(d,call2)}}for(var b{},dget_group.concat(Array.prototype.slice.call(arguments,0)),c0;cf.length;c++)a(fc);return b};a._i.push(b,d,g)};a.__SV1.2;bc.createElement(script);b.typetext/javascript;b.async!0;b.srcundefined!typeof MIXPANEL_CUSTOM_LIB_URL? MIXPANEL_CUSTOM_LIB_URL:file:c.location.protocol&&//cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js.match(/^\/\//)?https://cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js://cdn4.mxpnl.com/libs/mixpanel-2-latest.min.js;dc.getElementsByTagName(script)0;d.parentNode.insertBefore(b,d)}})(document,window.mixpanel||); mixpanel.init(c691fd262f33ce424f14e9dcaaeae414); // !-- end Mixpanel --> mixpanel.track(Page opened); document.getElementById(content).style.display block; document.getElementById(sidenav).style.visibility visible var sidenav new Sidenav({ content: document.getElementById(content), sidenav: document.getElementById(sidenav), backdrop: document.getElementById(backdrop) }); document.getElementById(menu-toggle).addEventListener(click, function () { mixpanel.track(Sidebar opened); sidenav.open(); }); setTimeout(() > { this.progress { width: 98%, transition-duration: 2s } }) let data { url : apelsin, referrer : document.referrer, query : document.location.search, new : 0 } if (!document.cookie.includes(_apelsin_session)) { let d new Date() d.setTime(d.getTime() + (24*60*60*1000)); document.cookie _apelsin_session 1; expires+ d.toUTCString(), data.new 1 } axios.post(https://tavqcni37c.execute-api.us-east-1.amazonaws.com/dev/sessionsDb, data) if (window.location.href.includes(?paid)) { this.isLoading true; console.log(Checking payment for, getQueryVariable(order_id)); let dataPayment { orderId: getQueryVariable(order_id) } axios.post(https://1gc5srj550.execute-api.us-east-1.amazonaws.com/dev/checkOrderPayment, dataPayment) .then((response)>{ console.log(response) let message let type if (response.data.status && response.data.status paid) { message Оплата совершена успешно. if (response.data.finalMessage) message + /br> + response.data.finalMessage type is-success } else { message Оплата не совершена. if (response.data.message) message message + br> Ответ платежной системы: br>br>i> + response.data.message +/i> type is-warning } this.isLoading false; this.$buefy.dialog.alert({ title: Статус оплаты, message: message, type: type, size: is-medium, confirmText: OK, canCancel: false, onConfirm: () > window.open(https://apelsin.savemenu.ru,_self) }) }) .catch((error) > console.log(error)) } if (window.location.href.includes(actioninstall)) { let message let installed false installed window.matchMedia((display-mode: standalone)).matches let canCancel false let confirmText OK if (!installed && (is.chrome() && is.mobile())) { canCancel true confirmText Да } if (installed) message Приложение уже установлено else if (!is.mobile()) message Откройте приложение на телефоне + br />img srchttps://apelsin.savemenu.ru/img/qr-code.png stylemax-height:300px;> else { if (is.chrome()) message Установить приложение? else if (is.opera()) message Для установки в браузере Opera откройте меню и нажмите На домашний экран. else if (is.firefox()) message Для установки в браузере Mozilla Firefox откройте меню и нажмите На домашний экран. else if (is.safari()) message Для установки в браузере Safari нажмите Поделиться и затем Добавить на домашний экран. else message Ваш браузер не поддерживает установку приложений. Откройте эту страницу в Chrome, FireFox, Opera, Edge или Safari для установки. } this.$buefy.dialog.alert({ title: Установка приложения, message: message, type: is-success, size: is-medium, confirmText: confirmText, canCancel: canCancel, cancelText: Нет, onConfirm: () > { if (installPrompt undefined) { // this.$buefy.toast.open(Installation is not availlablle in this browser) return } installPrompt.prompt(); installPrompt.userChoice.then(result > { if (result.outcome accepted) { //this.$ma.trackEvent({category: event, action: PWA installed: Chrome, label : null, value : null}); console.log(Installation done) } else { //this.$ma.trackEvent({category: event, action: PWA installation canceled: Chrome, label : null, value : null}); console.log(User denied install) } installPrompt null; }) } }) } function getQueryVariable(variable) { var query window.location.search.substring(1); var vars query.split(&); for (var i 0; i vars.length; i++) { var pair varsi.split(); if (decodeURIComponent(pair0) variable) { return decodeURIComponent(pair1); } } console.log(Query variable %s not found, variable); } } }) Vue.component(cart, { props: items, completed, ordering, currency, user_fields, name: cart, components: { }, data() { return { autocomplete: , editing: false, loading: false, deliveryLoading: false, orderNum: 0, fields: {name: Имя, value: , type: text, required: true}, {name: Адрес, value: , type: text, required: true}, {name: Телефон, value: , type: tel, required: true}, orderBtnActive: false, paymentModal: false, name: , email: , phoneObj: { number : { input: } }, address: , address1: , addrDetailed: {}, selectedPaymentMethod: {}, selectedDeliveryMethod: {}, deliveryFee: 0, phoneProps: { mode: international, defaultCountry: , disabledFetchingCountry: false, disabled: false, disabledFormatting: false, placeholder: , required: false, validCharactersOnly: true, enabledCountryCode: false, enabledFlags: false, onlyCountries: , autocomplete: off, name: telephone, maxLen: 20, wrapperClasses: , inputClasses: , dynamicPlaceholder: false, dropdownOptions: { disabledDialCode: true }, inputOptions: { showDialCode: false } } } }, template: ` div v-ifordering.active true idcart> div classheader p2> h1>Корзина/h1> /div> div v-ifcompleted classp2> b-message typeis-success > Заказ успешно оформлен. Номер заказа: {{orderNum}} /b-message> div v-ifselectedDeliveryMethod.message> b-message typeis-warning> {{selectedDeliveryMethod.message}} /b-message> /div> div v-ifselectedPaymentMethod.message> b-message typeis-warning> {{selectedPaymentMethod.message}} /b-message> /div> /div> div v-if!completed classcart-items style> div v-for(item, index) in items v-bind:keyitem.itemId classitem> div classclearfix> div v-ifitem.image ! 0 classcol col-2 stylemax-height:1rem;> div classimage stylewidth: 30px;height: 30px;margin-right: 10px; v-bind:style{ backgroundImage: url( + getIcon(item.image) + )} > /div> /div> div :class{col col-10: item.image !0} stylepadding:0> div classclearfix> div classcol col-8 :class{no-padding: item.image !0} stylepadding-right: 0;> div classname> {{item.itemName}} /div> /div> div classcol col-4 styletext-align: right;padding-left: 0;> div v-ifitem.noEdit classprice stylefont-size:14px; margin-left:10px @clickeditCartItem(item)> {{item.qty}} x {{item.itemPrice}} /div> div v-else classqty-change styletext-align: left;padding-left: 0;> div classinput-group input-number-group> div classinput-group-button @clickchangeQty(index, -1)> span classinput-number-decrement>-/span> /div> input classinput-number typenumber value1 min0 max1000 v-modelitem.qty> div classinput-group-button @clickchangeQty(index, 1)> span classinput-number-increment>+/span> /div> /div> /div> /div> /div> /div> /div> /div> /div> hr /> div classtotal p2 styletext-align:right> h3>Всего: {{cartTotal()}} {{currency}}/h3> /div> div v-if!completed idinputFields classfields p2 stylemargin-bottom:70px;> div classblock v-if!ordering.fields || !ordering.fields.name || !ordering.fields.name.hidden> b-field label-positionon-border labelИмя> b-input sizeis-medium required typetext validation-message* @blursaveField(name) custom-classname v-modelname refname>/b-input> /b-field> /div> div classblock v-if!ordering.fields || !ordering.fields.email || !ordering.fields.email.hidden> b-field label-positionon-border labelEmail> b-input sizeis-medium required typeemail validation-message* @blursaveField(email) custom-classemail v-modelemail refemail>/b-input> /b-field> /div> div classblock v-if!ordering.fields || !ordering.fields.phone || !ordering.fields.phone.hidden> b-field label-positionon-border labelТелефон> vue-tel-input @blursaveField(phone) @validate(e) > validatePhone(e) classmobile-phone v-modelphoneObj.number.input v-bindphoneProps />/vue-tel-input> /b-field> /div> div v-ifuser_fields v-forfield, index in user_fields classp1 :keyindex> b-field label-positionon-border :labelfield.name> b-input sizeis-medium :requiredfield.required :typefield.type :validation-messagefield.valMsg?valMsg:* @focusscrollIntoView(index) :custom-classfield+index v-modelfield.value refuserInputFields>/b-input> /b-field> /div> div classblock delivery stylebackground-color: #f0f0f0; padding: 12px; border-radius: 6px; color: #484848; v-ifordering.delivery && ordering.delivery.options> div classcolumns is-gapless is-mobile stylemargin-bottom:0;> div classcolumn> p stylepadding: 5px;font-weight: bold;vertical-align: bottom; classradio control-label> svg xmlnshttp://www.w3.org/2000/svg stylemargin-right: 10px; vertical-align: middle; width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-truck>rect x1 y3 width15 height13>/rect>polygon points16 8 20 8 23 11 23 16 16 16 16 8>/polygon>circle cx5.5 cy18.5 r2.5>/circle>circle cx18.5 cy18.5 r2.5>/circle>/svg> Доставка:/p> /div> div classcolumn styletext-align:right;> h3 stylefont-weight: bold;vertical-align: bottom; margin-bottom:0;> {{deliveryFee}} {{currency}} /h3> /div> /div> div classblock stylemargin-left: 23px;> div v-ifselectedDeliveryMethod.message> p classnote> {{selectedDeliveryMethod.message}} /p> /div> div stylepadding: 10px 0> b-radio v-modelselectedDeliveryMethod v-foroption, index in ordering.delivery.options v-ifoption.active :disabled checkDisabled(option) namedelivery required typeis-success @input$emit(change-delivery-option, option) :native-valueoption> {{option.name}} /b-radio> /div> div idaddress-block> div classblock v-ifselectedDeliveryMethod.type && selectedDeliveryMethod.type ! pickup> b-input sizeis-medium refstreet idaddress @blursaveField(address) v-modeladdress placeholderУлица required typetext validation-message* >/b-input> /div> div idaddress-detailed stylemargin-top: -18px; margin-bottom: 5px;> div styledisplay: inline-block; width: 30%; v-ifselectedDeliveryMethod.type && selectedDeliveryMethod.type ! pickup> b-input sizeis-medium refbuilding idbuilding v-modeladdrDetailed.building @blursaveField(addrDetailed) placeholderДом required typetel validation-message* >/b-input> /div> div styledisplay: inline-block; width: 30%; v-ifselectedDeliveryMethod.type && selectedDeliveryMethod.type ! pickup> b-input sizeis-medium refsub idsub @blursaveField(addrDetailed) v-modeladdrDetailed.sub placeholderКорпус typetel >/b-input> /div> div styledisplay: inline-block; width: 30%; v-ifselectedDeliveryMethod.type && selectedDeliveryMethod.type ! pickup> b-input sizeis-medium refapt idapartment v-modeladdrDetailed.apt @blursaveField(addrDetailed) placeholderКвартира typetel >/b-input> /div> /div> div classblock v-ifselectedDeliveryMethod.type && selectedDeliveryMethod.type ! pickup> b-input sizeis-medium rows2 idaddress1 @blursaveField(address1) v-modeladdress1 placeholderДополнитильно: код домофона, ориентиры, итд typetextarea validation-message* >/b-input> /div> /div> div v-ifselectedDeliveryMethod.type mrspeedy> b-button classbutton is-success :loadingdeliveryLoading @clickgetDeliveryFee> Get Delivery Fee /b-button> img srchttps://mrspeedy.my/img/my/logo.svg stylewidth:90px; display: inline-block;margin-top: 8px; margin-left: 7px;> /div> /div> /div> div classblock v-ifordering.payment && ordering.payment.options stylebackground-color: #f0f0f0; padding: 12px; border-radius: 6px; color: #484848;> p stylepadding: 5px;font-weight: bold;vertical-align: bottom; classradio control-label> svg xmlnshttp://www.w3.org/2000/svg stylemargin-right: 10px; vertical-align: middle; width24 height24 viewBox0 0 24 24 fillnone strokecurrentColor stroke-width2 stroke-linecapround stroke-linejoinround classfeather feather-credit-card>rect x1 y4 width22 height16 rx2 ry2>/rect>line x11 y110 x223 y210>/line>/svg> Оплата:/p> div classblock stylemargin-left: 23px;> div v-ifselectedDeliveryMethod.message> p classnote> {{selectedPaymentMethod.message}} /p> /div> div stylepadding: 10px 0> b-radio v-modelselectedPaymentMethod v-foroption, index in ordering.payment.options v-ifoption.active namepayment required typeis-success :native-valueoption> {{option.name}} /b-radio> /div> /div> /div> /div> b-modal :active.syncpaymentModal> div classcard stylemin-height:700px;> div classcard-content has-text-centered> h1>Оплата/h1> div idpayment>/div> /div> /div> /b-modal> div v-if!completed idcartButtonBar classfixed stylepadding: 0.7rem;width: 100%;max-width: 700px; bottom: 54px;text-align: center;z-index: 30;> b-button :loadingloading classbutton is-cta :class{is-light : !orderBtnActive, is-cta: orderBtnActive} stylepadding-left: 50px;padding-right: 50px;border-radius: 16px; @clickplaceOrder()>Заказать/b-button> /div> /div> `, mounted() { if (getCookie(name)) this.name getCookie(name) if (getCookie(email)) this.email getCookie(email) if (getCookie(phone)) this.phoneObj.number.input getCookie(phone) if (getCookie(address)) this.address getCookie(address) if (getCookie(address1)) this.address1 getCookie(address1) if (getCookie(addrDetailed)) this.addrDetailed JSON.parse(getCookie(addrDetailed)) if (this.selectedDeliveryMethod && this.selectedDeliveryMethod.type mrspeedy) this.createAutocomplete() function getCookie(cname) { var name _apelsin_ + cname + ; var decodedCookie decodeURIComponent(document.cookie); var ca decodedCookie.split(;); for(var i 0; i ca.length; i++) { var c cai; while (c.charAt(0) ) { c c.substring(1); } if (c.indexOf(name) 0) { let a c.substring(name.length, c.length) return a; } } return; } }, watch: { selectedDeliveryMethod(newVal) { this.getDeliveryFee(); if (this.selectedDeliveryMethod.type mrspeedy) this.createAutocomplete() } }, methods: { validatePhone(e) { console.log(event:, e); this.phone e; }, createAutocomplete() { console.log(Starting createAutocomplete()) this.$nextTick(() > { this.autocomplete new google.maps.places.Autocomplete( this.$refs.autocomplete, { fields: formatted_address, ComponentRestrictions : { country: ru }, types: , language: ru }); this.autocomplete.addListener(place_changed, () > { let place this.autocomplete.getPlace(); console.log(place) this.address place.formatted_address }) }) }, saveField(field) { console.log(field); if (field phone) { document.cookie _apelsin_ + phone + + this.phone.number.e164 +; } else if (field addrDetailed) { document.cookie _apelsin_ + addrDetailed + + JSON.stringify(this.addrDetailed) +; } else document.cookie _apelsin_ + field + + thisfield +; }, checkDisabled(option) { if (!option.minAmt) return false else if (option.minAmt > this.cartTotal() - this.deliveryFee) return true else return false }, checkCondition(condition) { return eval(condition) }, onPlaceChanged() { console.log(this.autocomplete.getPlace()) }, getIcon(img) { let url ; if (img 0) url ; else if (img.includes(/)) url https://savemenu.ru/ + img; else url https://savemenu.ru/_public/icons/ + img + .png; return url; }, cartTotal() { let total 0; for (let i0; i this.items.length; i++) { total total + parseFloat(this.itemsi.itemPrice) * this.itemsi.qty } total + this.deliveryFee total Math.round(total * 100) / 100 return total }, getDeliveryFee() { console.log(Starting getDeliveryFee()) if (!this.ordering&&this.ordering.delivery&&this.ordering.delivery.options) return let c this.selectedDeliveryMethod.cost if (c) { if (c.includes(func_)) { thisc() } else this.deliveryFee parseInt(c) } }, func_mrSpeedyCalculate() { if (this.address ) return 0 console.log(Starting func_mrSpeedyCalculate()) this.deliveryLoading true; let params { url: apelsin, addressTo: this.address + , + this.address1, addressFrom: Нарвская ул., 21, Москва, Россия, 125212 } axios.post(https://qc63hbjbvb.execute-api.us-east-1.amazonaws.com/dev/getDeliveryCost, params) .then((response)>{ console.log(response.data) let fee parseInt(response.data) this.deliveryFee fee; this.deliveryLoading false; this.$emit(change-delivery-option, {type: mrspeedy, cost: fee}) }) .catch ((error) > { console.log(error) this.deliveryLoading false; }) }, changeQty(i, inc) { this.itemsi.qty this.itemsi.qty + inc; // this.itemsi.itemPrice++; // this.itemsi.itemPrice--; this.itemsi.itemPrice Math.round(this.itemsi.itemPrice * 100) / 100 if (this.itemsi.qty 0) this.items.splice(i, 1); this.$forceUpdate(); }, editCartItem(item) { Vue.set(item,editMode,true) setTimeout(() > { item.editModefalse }, 2000) }, scrollIntoView(index){ let field document.getElementsByClassName(field+index)0 console.log(field); setTimeout(function() { field.scrollIntoView(); }, 100); }, placeOrder() { let validated false validated this.checkValidation(this.$refs) if (validated) { let orderNum Date.now().toString().slice(-4); let data {} data.order this.items data.fields this.fields data.name this.name data.email this.email data.phone this.phoneObj.number.input data.addressFrom Нарвская ул., 21, Москва, Россия, 125212 if (this.selectedDeliveryMethod.type ! pickup) { data.address this.address if (this.addrDetailed ! {}) { data.address data.address + , + Object.keys(this.addrDetailed).map((k) > {return this.addrDetailedk}).join(, ); } data.addrDetailed this.addrDetailed; data.address1 this.address1 } else { data.address data.address1 data.addrDetailed {} } data.selectedPaymentMethod this.selectedPaymentMethod if (this.ordering && this.ordering.delivery) data.selectedDeliveryMethod this.selectedDeliveryMethod data.url apelsin data.vendorName Apelsin RK data.vendorPhone +74957771967 доб. 1580 data.finalMessage Спасибо за заказ. Еда будет готова в течение 30 минут. data.domain savemenu.ru data.subdomain window.location.hostname data.to this.ordering.email data.telegramId 1112141061 data.orderNum orderNum data.orderTotal this.cartTotal(); data.currency ₽ data.referrer document.referrer data.fullUrl window.location.href data.integrations this.ordering.integrations this.loading true axios.post(https://1gc5srj550.execute-api.us-east-1.amazonaws.com/dev/placeOrder, data) .then((response)>{ console.log(response) if (response.data.next && response.data.next redirect && response.data.url) { window.open(response.data.url, _self) } else { this.orderNum response.data.orderNum this.$emit(order-placed) this.loading false } }) } else document.getElementById(inputFields).scrollIntoView(); }, checkValidation(refs) { for (let field in refs) { if (refsfield && field ! autocomplete) if (!refsfield.checkHtml5Validity()) { console.log(Not filled:, refsfield.$attrs.placeholder); if (refsfield.$attrs && refsfield.$attrs.placeholder) this.$buefy.toast.open(Есть незаполненные поля: + refsfield.$attrs.placeholder) else this.$buefy.toast.open(Есть незаполненные поля) return false } } if (!this.phone.number || this.phone.number.input ) { this.$buefy.toast.open(Введите номер телефона) return false } if (!this.phone.isValid) { this.$buefy.toast.open(Проверьте номер телефона) return false } if (refs.autocomplete && refs.autocomplete.value ) return false if (this.ordering && this.ordering.delivery && this.ordering.delivery.options && this.ordering.delivery.options.length > 0 && !this.selectedDeliveryMethod.type) { this.$buefy.toast.open(Выберите способ доставки) return false } if (this.ordering && this.ordering.payment && this.ordering.payment.options && this.ordering.payment.options.length > 0 && !this.selectedPaymentMethod.type) { this.$buefy.toast.open(Выберите способ оплаты) return false } return true } }, }) /script> script async srchttps://www.googletagmanager.com/gtag/js?idUA-128206529-1>/script> script> // !-- PWA --!> if (serviceWorker in navigator) { window.addEventListener(load, () > { navigator.serviceWorker.register(./service-worker.js) .then(registration > { console.log(Service Worker registered); navigator.serviceWorker.ready .then(function(registration) { console.log(Service Worker ready); if (!registration.pushManager) console.log(No pushManager) else { return registration.pushManager.getSubscription() .then(async function(subscription) { // If a subscription was found, return it. if (subscription) { for(var i 0; i subscribeCards.length; i++){ subscribeCardsi.style.display none; } return subscription; } else { for(var i 0; i subscribeCards.length; i++) subscribeCardsi.style.display block; } }) } }) }) .catch(err > SW registration failed) }); } // !-- custom_functions --> function flattenList(menu) { let list ; menu.forEach(item > { if (item.itemType item && !item.isHidden) { if (item.itemTags) item.search item.search + + item.itemTags.toString(); list.push(item); } else if (!item.isHidden && item.itemType Header && item.subitems) item.subitems.forEach(subitem > { if (!subitem.isHidden && subitem.itemType item) { subitem.search subitem.itemName + + item.itemName if (subitem.itemTags) subitem.search subitem.search + + subitem.itemTags.toString(); list.push(subitem) } }) }) return list; } function getTags(menu) { let tags ; menu.forEach(item > { if (item.itemTags && !item.isHidden) { item.itemTags.forEach(tag > { if (tags.indexOf(tag) -1) tags.push(tag) }) } if (!item.isHidden && item.itemType Header && item.subitems) { item.subitems.forEach(subitem > { if (!subitem.isHidden && subitem.itemTags) { subitem.itemTags.forEach(tag > { if (tags.indexOf(tag) -1) tags.push(tag) }) } }) } }) return tags; } var subscribeCards document.getElementsByClassName(subscribePush); function subscribeToPush() { askPermission() .then(() > { const vapidPublicKey BM8fzcpJUIRUNlsJybde9kjW8D0B1YMT11za2sZMxxuPa3C4_aw4d-SUkMl4iYmospCHDO8tYvgInqYfh4J5d-I const convertedVapidKey urlBase64ToUint8Array(vapidPublicKey); navigator.serviceWorker.ready .then(async function (registration) { return registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: convertedVapidKey }) .then(function (subscription) { for (var i 0; i subscribeCards.length; i++) { subscribeCardsi.style.display none; } var data JSON.stringify({ url: apelsin, subscription: JSON.stringify(subscription), messageTitle: На связи, messageBody: Подписка оформлена успешно! 👍 }); var xhr new XMLHttpRequest(); xhr.addEventListener(readystatechange, function () { if (this.readyState 4) { console.log(xhr.status + + xhr.responseText); mixpanel.track(Subscribed to push, { info: navigator.userAgent }); } }); xhr.open(POST, https://imll569o22.execute-api.ap-south-1.amazonaws.com/1); xhr.setRequestHeader(Content-Type, application/json); xhr.send(data); }); }); }); } function askPermission() { if (!Notification) { this.$buefy.toast(Browser not supported) return } return new Promise(function (resolve, reject) { const permissionResult Notification.requestPermission(function (result) { resolve(result); }); if (permissionResult) { permissionResult.then(resolve, reject); } }) .then(function (permissionResult) { if (permissionResult ! granted) { throw new Error(We were not granted permission.); } }); }; function urlBase64ToUint8Array(base64String) { const padding .repeat((4 - base64String.length % 4) % 4); const base64 (base64String + padding) .replace(/-/g, +) .replace(/_/g, /); const rawData window.atob(base64); return Uint8Array.from(...rawData.map((char) > char.charCodeAt(0))); } /script> !-- Yandex.Metrika counter --> script typetext/javascript> (function (m, e, t, r, i, k, a) { mi mi || function () { (mi.a mi.a || ).push(arguments) }; mi.l 1 * new Date(); k e.createElement(t), a e.getElementsByTagName(t)0, k.async 1, k.src r, a.parentNode.insertBefore( k, a) }) (window, document, script, https://mc.yandex.ru/metrika/tag.js, ym); ym(52602847, init, { id: 52602847, clickmap: true, trackLinks: true, accurateTrackBounce: true, webvisor: true }); /script> noscript> div>img srchttps://mc.yandex.ru/watch/52602847 styleposition:absolute; left:-9999px; alt />/div> /noscript> !-- /Yandex.Metrika counter --> script> ! function (f, b, e, v, n, t, s) { if (f.fbq) return; n f.fbq function () { n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments) }; if (!f._fbq) f._fbq n; n.push n; n.loaded !0; n.version 2.0; n.queue ; t b.createElement(e); t.async !0; t.src v; s b.getElementsByTagName(e)0; s.parentNode.insertBefore(t, s)}(window, document, script, https://connect.facebook.net/en_US/fbevents.js);fbq(init, 218793352362568);fbq(track, PageView);!-- Global site tag (gtag.js) - Google Analytics -->window.dataLayer window.dataLayer || ;function gtag(){dataLayer.push(arguments);}gtag(js, new Date());gtag(config, UA-128206529-1);/script> /body> /html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]