1app.rwPhotoComponent={props:['preview','isMore','uploading','percent'],methods:{onDelete(){this.$emit('delete')}},template:` 2 <div class="rwPhoto" :class="{'rwPhoto--more': isMore}"> 3 <template v-if="preview"> 4 <div class="rwPhoto__delete" @click.stop="onDelete"></div> 5 <div class="rwPhoto__wrap"> 6 <img class="rwPhoto__img" :src="preview" /> 7 </div> 8 </template> 9 <div v-else class="rwPhoto__upload" :class="{'rwPhoto__upload--uploading': uploading}"> 10 <div v-if="uploading" class="rwPhoto__progress"> 11 {{ percent }}% 12 </div> 13 <span v-if="isMore && !uploading">+1</span> 14 </div> 15 </div> 16 `};app.rwStarComponent={props:['value','halfStep'],data(){return{hoverValue:0,isHovering:!1,max:5,}},methods:{resolveValue(index,event){if(!this.halfStep){return index} 17const target=event.currentTarget;const bounds=target.getBoundingClientRect();const x=(event.clientX!==undefined?event.clientX:event.touches&&event.touches[0].clientX)-bounds.left;return x<bounds.width/2?index-0.5:index},onHover(index,event){this.hoverValue=this.resolveValue(index,event);this.isHovering=!0},onLeave(){this.isHovering=!1;this.hoverValue=0},onClick(index,event){this.$emit('input',this.resolveValue(index,event))},fillClass(index){const current=this.isHovering?this.hoverValue:this.value;if(current>=index){return'rwStar__ico--full'} 18if(current>=index-0.5){return'rwStar__ico--half'} 19return''}},template:` 20 <div class="rwStar" @mouseleave="onLeave"> 21 <span v-for="i in max" 22 :key="i" 23 class="rwStar__wrapper" 24 @mousemove="onHover(i, $event)" 25 @click="onClick(i, $event)"> 26 <svg class="rwStar__ico" 27 :class="fillClass(i)" 28 width="20" 29 height="19"
30 viewBox="0 0 31 29" 31 fill="none" 32 xmlns="http://www.w3.org/2000/svg"> 33 <defs> 34 <clipPath :id="'rwStarHalf' + _uid + '_' + i"> 35 <rect x="0" y="0" width="15.5" height="29"/> 36 </clipPath> 37 </defs> 38 <path class="rwStar__icoBg" 39 d="M13.118 1.67218C13.8835 -0.557392 17.1165 -0.557392 17.882 1.67218L19.874 7.47404C20.2143 8.46523 21.1618 9.13669 22.2334 9.14608L28.5059 9.20118C30.9163 9.22237 31.9154 12.2215 29.9781 13.6207L24.9367 17.2615C24.0754 17.8835 23.7135 18.97 24.0355 19.9669L25.9201 25.8029C26.6443 28.0455 24.0288 29.8991 22.0659 28.5343L16.9582 24.9825C16.0856 24.3758 14.9144 24.3758 14.0418 24.9825L8.93407 28.5343C6.97124 29.8991 4.35566 28.0455 5.07988 25.8029L6.9645 19.9669C7.28646 18.97 6.92456 17.8835 6.06326 17.2615L1.02193 13.6207C-0.915399 12.2215 0.0836817 9.22237 2.49407 9.20118L8.7666 9.14608C9.83819 9.13669 10.7857 8.46523 11.126 7.47404L13.118 1.67218Z"/> 40 <path class="rwStar__icoFill" 41 :clip-path="'url(#rwStarHalf' + _uid + '_' + i + ')'" 42 d="M13.118 1.67218C13.8835 -0.557392 17.1165 -0.557392 17.882 1.67218L19.874 7.47404C20.2143 8.46523 21.1618 9.13669 22.2334 9.14608L28.5059 9.20118C30.9163 9.22237 31.9154 12.2215 29.9781 13.6207L24.9367 17.2615C24.0754 17.8835 23.7135 18.97 24.0355 19.9669L25.9201 25.8029C26.6443 28.0455 24.0288 29.8991 22.0659 28.5343L16.9582 24.9825C16.0856 24.3758 14.9144 24.3758 14.0418 24.9825L8.93407 28.5343C6.97124 29.8991 4.35566 28.0455 5.07988 25.8029L6.9645 19.9669C7.28646 18.97 6.92456 17.8835 6.06326 17.2615L1.02193 13.6207C-0.915399 12.2215 0.0836817 9.22237 2.49407 9.20118L8.7666 9.14608C9.83819 9.13669 10.7857 8.46523 11.126 7.47404L13.118 1.67218Z"/> 43 </svg> 44 </span> 45 </div> 46 `};app.rwItemRatingComponent={components:{rwStar:app.rwStarComponent,},props:['item','placeholder','halfStep'],directives:{autogrow:{inserted(el){app.autogrow(el)}},},methods:{onInput(value){this.$set(this.item,'value',value)}},template:` 47 <div class="rwItemRating"> 48 <div class="rwItemRating__header"> 49 <span class="rwItemRating__name" 50 :class="{'rwItemRating__name--required': item.required}">{{ item.name }}</span> 51 <rwStar :value="item.value || 0" 52 :half-step="halfStep" 53 @input="onInput"/> 54 </div> 55 <textarea v-if="item.showComment" 56 class="rwItemRating__textarea" 57 v-model="item.text" 58 v-autogrow 59 :placeholder="placeholder"></textarea> 60 </div> 61 `};app.rwDishRatingComponent={components:{rwStar:app.rwStarComponent,},props:['item','placeholder','halfStep','countLabel'],directives:{autogrow:{inserted(el){app.autogrow(el)}},},computed:{meta(){const parts=[];if(this.item.price!==undefined&&this.item.price!==null&&this.item.price!==''){parts.push(this.item.price)} 62if(this.item.count){parts.push(this.item.count+(this.countLabel?' '+this.countLabel:''))} 63return parts.join(' · ')},showComment(){return this.item.showComment&&this.item.value>0}},methods:{onInput(value){this.$set(this.item,'value',value)}},template:` 64 <div class="rwDish"> 65 <div class="rwDish__top"> 66 <div class="rwDish__img"> 67 <img v-if="item.image" class="rwDish__imgPic" :src="item.image" alt=""/> 68 </div> 69 <div class="rwDish__info"> 70 <div class="rwDish__name">{{ item.name }}</div> 71 <div v-if="meta" class="rwDish__meta">{{ meta }}</div> 72 </div> 73 </div> 74 <rwStar :value="item.value || 0" 75 :half-step="halfStep" 76 @input="onInput"/> 77 <textarea v-if="showComment" 78 class="rwDish__txt" 79 v-model="item.text" 80 v-autogrow 81 :placeholder="placeholder"></textarea> 82 </div> 83 `};app.rwCartFormComponent={components:{commonFormSubmit:app.commonFormSubmitComponent,commonUpload:app.commonUploadComponent,rwPhoto:app.rwPhotoComponent,rwItemRating:app.rwItemRatingComponent,rwDishRating:app.rwDishRatingComponent,commonSpinner:app.commonSpinnerComponent,},props:['loc','company','cartId'],data(){return{isReady:!1,loading:!1,order:null,ratings:[],halfStep:!1,txt:'',images:[],uploadUrl:`https://${document.domain === 'web2.foodpicasso.com' ? 'beta-panel' : 'app'}.foodpicasso.com/upload/`,dishesExpanded:!1,agreementChecked:!0,}},computed:{orderRatings(){return this.ratings.filter((r)=>r.type!=='dish'&&!(r.type==='criterion'&&r.scope==='dish'))},overallRating(){return this.ratings.find((r)=>r.type==='mark_overall')||null},criteriaRatings(){return this.orderRatings.filter((r)=>r.type!=='mark_overall')},dishRatings(){return this.ratings.filter((r)=>r.type==='dish'||(r.type==='criterion'&&r.scope==='dish'))},visibleDishes(){if(this.dishesExpanded||this.dishRatings.length<=2){return this.dishRatings} 84return this.dishRatings.slice(0,2)},hasHiddenDishes(){return this.dishRatings.length>2},hasUploadingImages(){return this.images.some((image)=>image.uploading)},canSubmit(){return this.agreementChecked&&!this.loading}},mounted(){this.getData()},methods:{getData(){const payload={meta:{cart:this.cartId}};app.fetch('/review/cart/get',payload,(res)=>{if(res.error){app.alert(res.message,'danger');this.$emit('close');return} 85this.ratings=(res.ratings||[]).map((r)=>Object.assign({value:0,text:'',halfStep:!1,showComment:r.type==='dish'||r.hasComment===!0,},r));this.order=res.order||null;this.halfStep=Number(res.scale)===10;this.isReady=!0})},onUploadProgress(event){let image=this.images.find((img)=>img.id===event.id);if(!image){image={id:event.id,src:'',preview:'',percent:0,uploading:!0,type:'photo',};this.images.push(image);return} 86image.percent=event.value},onUploadSuccess(event){const image=this.images.find((img)=>img.id===event.id);if(!image){return} 87if(!event.image||!event.image.src){this.images.splice(this.images.indexOf(image),1);app.alert(this.loc['review/err/uploading'],'danger');return} 88image.src=event.image.src;image.preview=event.image.preview||event.image.src;image.percent=100;image.uploading=!1},onUploadError(event){const image=this.images.find((img)=>img.id===event.id);if(image){this.images.splice(this.images.indexOf(image),1)} 89app.alert(this.loc['review/err/uploading'],'danger')},onDeletePhoto(image){const index=this.images.indexOf(image);if(index!==-1){this.images.splice(index,1)}},toggleDishes(){this.dishesExpanded=!this.dishesExpanded},onSave(){if(!this.canSubmit){return} 90if(this.hasUploadingImages){app.alert(this.loc['review/err/uploading'],'danger');return} 91this.loading=!0;const payload={ratings:this.ratings,txt:this.txt,images:this.images.filter((img)=>img.src).map((img)=>({src:img.src,type:img.type})),meta:{cart:this.cartId}};app.fetch('/review/cart/add',payload,(res)=>{if(res.error){app.alert(res.message,'danger');this.loading=!1;return} 92app.alert(this.loc['review/success']);this.$emit('close')})}},directives:{autogrow:app.autogrow,},template:` 93 <div class="cReview"> 94 95 <div class="cReview__loader" v-if="!isReady"> 96 <commonSpinner/> 97 </div> 98 99 <template v-else> 100 101 <div class="cReview__header"> 102 <div class="cReview__title">{{ loc['review/cart/title'] }}</div> 103 <div class="cReview__subtitle">{{ loc['review/cart/subtitle'] }}</div> 104 </div> 105 106 <div class="cReview__content"> 107 108 <div class="cReview__card cReview__order" v-if="order"> 109 <div class="cReview__orderRow"> 110 <div class="cReview__orderPrimary">
110{{ loc['history/order'] }}{{ order.num }}</div> 111 <div class="cReview__orderSecondary" v-if="order.date">{{ order.date }}</div> 112 </div> 113 <div class="cReview__orderRow" v-if="order.address || order.deliveryType"> 114 <div class="cReview__orderPrimary" v-if="order.address">{{ order.address }}</div> 115 <div class="cReview__orderSecondary" v-if="order.deliveryType">{{ order.deliveryType }}</div> 116 </div> 117 </div> 118 119 <div class="cReview__card cReview__ratings" v-if="overallRating"> 120 <rwItemRating :item="overallRating" 121 :half-step="halfStep" 122 :placeholder="loc['review/text']"/> 123 </div> 124 125 <div class="cReview__card cReview__ratings" v-if="criteriaRatings.length"> 126 <rwItemRating v-for="rating of criteriaRatings" 127 :key="rating.id" 128 :item="rating" 129 :half-step="halfStep" 130 :placeholder="loc['review/text']"/> 131 </div> 132 133 <div class="cReview__card cReview__dishes" v-if="dishRatings.length"> 134 <rwDishRating v-for="rating of visibleDishes" 135 :key="rating.id" 136 :item="rating" 137 :half-step="halfStep" 138 :count-label="loc['order/piece/name']" 139 :placeholder="loc['review/text']"/> 140 141 <button v-if="hasHiddenDishes" 142 class="cReview__toggle" 143 :class="{'cReview__toggle--expanded': dishesExpanded}" 144 type="button" 145 @click="toggleDishes"> 146 <span>{{ dishesExpanded ? loc['review/dishes/collapse'] : loc['review/dishes/expand'] }}</span> 147 <svg class="cReview__toggleIcon" width="14" height="8" viewBox="0 0 14 8" xmlns="http://www.w3.org/2000/svg"> 148 <path d="M1 1L7 7L13 1" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"/> 149 </svg> 150 </button> 151 </div> 152 153 <div class="cReview__photos"> 154 <rwPhoto v-for="image in images" 155 :key="image.id" 156 :preview="image.preview" 157 :uploading="image.uploading" 158 :percent="image.percent" 159 @delete="onDeletePhoto(image)"/> 160 161 <commonUpload :url="uploadUrl" 162 @progress="onUploadProgress" 163 @success="onUploadSuccess" 164 @error="onUploadError"> 165 <rwPhoto :is-more="images.length > 0"/> 166 </commonUpload> 167 </div> 168 169 <div class="cReview__card"> 170 <textarea class="cReview__txt" 171 v-model="txt" 172 v-autogrow 173 :placeholder="loc['review/text']"></textarea> 174 </div> 175 176 <label class="cReview__agreement"> 177 <span class="cReview__agreementBox" 178 :class="{'cReview__agreementBox--checked': agreementChecked}"> 179 <input type="checkbox" 180 class="cReview__agreementInput" 181 v-model="agreementChecked"> 182 </span> 183 <span class="cReview__agreementText">{{ loc['review/agreement'] }}</span> 184 </label> 185 186 <commonFormSubmit class="cReview__submit" 187 :text="loc['btn/send']" 188 :loading="loading" 189 :disabled="!canSubmit" 190 no-wrapper="true" 191 @submit="onSave()"/> 192 193 </div> 194 195 </template> 196 197 </div> 198 `};app.addModule(()=>{const show=(e,params)=>{app.openViewer({backgroundColor:'#f2f2f2',desktop:{maxWidth:'400px',class:'reviewCartForm',},mobile:{bgClose:!0,withTick:!0,maxHeight:'90dvh',class:'reviewCartForm',},component:{components:{rwCartForm:app.rwCartFormComponent,},props:['params'],methods:{onClose(){this.$emit('close');PubSub.publish('refetchOrders')}},template:`<rwCartForm :loc="params.loc" 199 :cart-id="params.cartId" 200 @close="onClose"/>`,},props:{params},})};if(!PubSub.countSubscriptions('showCartReviewForm')){PubSub.subscribe('showCartReviewForm',show)}});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.