PageSourceSearch

https://hub.avibox.ru/assets/AdminPromoCodes-i5RzNGMV.js

js avibox.ru collected 2026-09-24 15:12:51 UTC 17,382 bytes, 1 lines download raw bytes

1import{dI as Ce,ed as x,eb as V,dw as H,e3 as Ue,e5 as Se,ei as we,e7 as o,dB as n,dy as t,dF as c,er as v,c3 as Te,dE as f,eH as u,eC as y,eB as N,dz as F,dA as S,eG as k,eJ as $,a$ as Ve,dZ as J,ej as $e,ay as Ae,ax as Ie,cZ as Ee,em as d,dp as O,aL as R,ef as X}from"./vendor-DUoYKxKf.js";import{T as ze}from"./Table-BWHKNJiS.js";import{e as K,T as De,d as Pe}from"./index-BcPf-nBI.js";import{S as q}from"./StatusPill-BD38qi8e.js";import{C as Be}from"./ConfirmPopup-hxhE88wv.js";import{E as Le}from"./ErrorState-D7_jXPui.js";import{u as Me}from"./useToast-DR0vBTf1.js";import{u as Ne}from"./useAdminApi-UfAK0RZx.js";import{m as Fe}from"./apiErrors-5QjOq92y.js";import"./CopyButton.vue_vue_type_script_setup_true_lang-DUqHItUu.js";import"./clipboard-Dw6gfW3R.js";import"./ProfileAvatar-B9TVcWCe.js";import"./avatar-placeholder-MmQ9fg6u.js";import"./usePersistentSetting-CkvRMRs-.js";import"./vue-core-BW8FD41h.js";const Oe={class:"admin-page"},Re={class:"admin-page__header"},qe={class:"admin-page__header-actions"},We=["disabled"],Ze={class:"toolbar"},je={class:"code-badge"},Ge={key:0},He={key:1},Je={class:"period-cell"},Xe={key:0},Ke={key:1},Qe={class:"text-muted"},Ye={class:"row-actions"},et=["onClick"],tt=["onClick"],st=["onClick"],lt={class:"modal modal--wide"},it={class:"modal__header"},ot={class:"modal__body"},nt={class:"fields-row"},at={class:"field"},dt={class:"field"},rt={class:"fields-row"},ut={class:"field"},_t={class:"field__label"},pt={class:"field__hint-inline"},ct=["max"],mt={class:"field"},vt={class:"fields-row"},ft={class:"field"},bt={class:"field"},yt={class:"fields-row"},gt={class:"field"},ht={class:"field"},xt={class:"field"},kt={class:"user-search-wrap"},Ct={key:0,class:"user-search-dropdown"},Ut=["onClick"],St={class:"user-search-item__login"},wt={class:"user-search-item__id"},Tt={key:0,class:"bound-user-chip"},Vt={class:"field"},$t={key:0,class:"modal__error modal__error--inline"},At={class:"modal__footer"},It=["disabled"],Et=["disabled"],zt={key:0},Dt={key:1},Pt={class:"modal modal--wide"},Bt={class:"modal__header"},Lt={class:"modal__title"},Mt={class:"code-badge"},Nt={class:"modal__body modal__body--table"},Ft={key:0,class:"modal__loading"},Ot={class:"act-table"},Rt={class:"mono"},qt={class:"mono"},Wt={class:"mono"},Zt={key:1,class:"text-muted"},jt={key:0,class:"act-table__more"},Gt={key:2,class:"empty-hint"},Ht={class:"modal__footer"},Q=20,Jt=Ce({__name:"AdminPromoCodes",setup(Xt){const{listPromoCodes:Y,createPromoCode:ee,updatePromoCode:te,deletePromoCode:se,getPromoActivations:le,getUsers:ie}=Ne(),oe={disabled:"Откл.",expired:"Истёк",exhausted:"Исчерпан",scheduled:"Запланирован",active:"Активен"},ne={active:"success",scheduled:"primary",exhausted:"warning",expired:"danger",disabled:"neutral"},ae=[{header:"Код",key:"code",minWidth:"130px"},{header:"Тип",key:"promo_type",width:"140px"},{header:"Значение",key:"value",width:"110px"},{header:"Использ.",key:"usage",width:"100px",textAlign:"center"},{header:"На юзера",key:"per_user_limit",width:"90px",textAlign:"center"},{header:"Период",key:"period",minWidth:"180px"},{header:"Для кого",key:"bound_user",minWidth:"120px"},{header:"Статус",key:"status",width:"120px"},{header:"",key:"actions",width:"100px"}],g=x([]),w=x(!1),A=x(!1),I=x(!1),E=x(null);let D=1;const m=V({search:"",promo_type:"",is_active:"true"}),{toast:z,showSuccess:P,showError:W,showToast:de}=Me(),re=H(()=>g.value.map(l=>({id:l.id,code:l.code,promo_type:l.promo_type,value:l.value,max_discount_rub:l.max_discount_rub,usage_limit:l.usage_limit,used_count:l.used_count,per_user_limit:l.per_user_limit,valid_from:l.valid_from,valid_until:l.valid_until,is_active:l.is_active,bound_user_login:l.bound_user_login,status:l.status})));async function Z(l=!0){var e,p;if(l)w.value=!0,D=1,I.value=!1;else{if(w.value||A.value||I.value)return;A.value=!0}E.value=null;try{const s={page:D,size:Q};m.promo_type&&(s.promo_type=m.promo_type),m.search&&(s.search=m.search),m.is_active!==""&&(s.is_active=m.is_active==="true");const b=await Y(s);g.value=l?b.items:[...g.value,...b.items],I.value=b.items.length<Q,D+=1}catch(s){E.value=((p=(e=s==null?void 0:s.response)==null?void 0:e.data)==null?void 0:p.detail)??"Не удалось загрузить данные",l&&(g.value=[])}finally{w.value=!1,A.value=!1}}function ue(){return Z(!1)}function C(){Z(!0)}function j(){C()}let T=null;function _e(){T&&clearTimeout(T),T=setTimeout(()=>C(),400)}function B(l){if(l==null)return"—";const e=parseFloat(l);
1return isNaN(e)?"—":e.toLocaleString("ru-RU",{minimumFractionDigits:2,maximumFractionDigits:2})+" ₽"}function L(l){return new Date(l).toLocaleString("ru-RU",{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"})}async function pe(l){const e=String(l.id),p=!l.is_active;try{const s=await te(e,{is_active:p}),b=g.value.findIndex(ke=>ke.id===e);b!==-1&&(g.value[b]=s),P(p?"Промокод активирован":"Промокод деактивирован")}catch(s){W(s,"Ошибка обновления")}}const _=V({visible:!1,id:"",code:"",loading:!1});function ce(l){_.visible=!0,_.id=String(l.id),_.code=String(l.code),_.loading=!1}async function me(){_.loading=!0;try{await se(_.id),g.value=g.value.filter(l=>String(l.id)!==_.id),_.visible=!1,P("Промокод удалён"),C()}catch(l){W(l,"Ошибка удаления")}finally{_.loading=!1}}const r=V({open:!1,loading:!1,error:null}),i=V({code:"",promo_type:"percent",value:"",max_discount_rub:"",usage_limit:"",per_user_limit:1,valid_from:"",valid_until:"",description:"",bound_user_id:null}),ve=x(null);function fe(l,e){Object.assign(i,{code:"",promo_type:"percent",value:"",max_discount_rub:"",usage_limit:"",per_user_limit:1,valid_from:"",valid_until:"",description:"",bound_user_id:null}),U.value="",h.value=[],ve.value=null,r.open=!0,r.error=null}const U=x(""),h=x([]);let M=null;function be(){i.bound_user_id=null,h.value=[],M&&clearTimeout(M);const l=U.value.trim();l.length<2||(M=setTimeout(async()=>{try{const e=await ie({q:l,size:5,page:1});h.value=e.users.map(p=>({id:p.id,login:p.login}))}catch{h.value=[]}},300))}function ye(l){i.bound_user_id=l.id,U.value=l.login,h.value=[]}function ge(){i.bound_user_id=null,U.value="",h.value=[]}const G=H(()=>{if(!i.code.trim())return!1;const l=parseFloat(i.value);return!(isNaN(l)||l<=0||i.promo_type==="percent"&&l>100)});async function he(){var l;if(G.value){r.loading=!0,r.error=null;try{const e={code:i.code.trim().toUpperCase(),promo_type:i.promo_type,value:i.value,per_user_limit:i.per_user_limit,first_payment_only:!1};i.max_discount_rub&&(e.max_discount_rub=i.max_discount_rub),i.usage_limit&&(e.usage_limit=Number(i.usage_limit)),i.valid_from&&(e.valid_from=new Date(i.valid_from).toISOString()),i.valid_until&&(e.valid_until=new Date(i.valid_until).toISOString()),i.description.trim()&&(e.description=i.description.trim()),i.bound_user_id&&(e.bound_user_id=i.bound_user_id),await ee(e),r.open=!1,P(`Промокод «${e.code}» создан`),C()}catch(e){((l=e==null?void 0:e.response)==null?void 0:l.status)===409?r.error="Промокод с таким кодом уже существует":r.error=Fe(e,"Ошибка создания")[0],de(r.error??"","error")}finally{r.loading=!1}}}const a=V({open:!1,loading:!1,code:"",promoId:"",items:[],total:0});async function xe(l){a.open=!0,a.code=String(l.code),a.promoId=String(l.id),a.items=[],a.total=0,a.loading=!0;try{const e=await le(a.promoId,{page:1,size:50});a.items=e.items,a.total=e.total}catch{a.items=[]}finally{a.loading=!1}}return Ue(()=>{C()}),Se(()=>{T&&clearTimeout(T)}),(l,e)=>{const p=we("tooltip");return o(),n("div",Oe,[t("div",Re,[e[24]||(e[24]=t("div",{class:"admin-
1page__header-left"},[t("h1",{class:"admin-page__title"},"Промокоды"),t("p",{class:"admin-page__subtitle"},"Создание и управление промокодами")],-1)),t("div",qe,[t("button",{class:"refresh-btn",disabled:w.value,onClick:C},[c(K,{size:15,inline:""})],8,We),t("button",{class:"btn btn--primary",onClick:e[0]||(e[0]=s=>fe())},[c(v(Te),{size:15}),e[23]||(e[23]=f(" Создать "))])])]),t("div",Ze,[u(t("input",{"onUpdate:modelValue":e[1]||(e[1]=s=>m.search=s),type:"text",class:"filter-input",placeholder:"Поиск по коду…",onInput:_e},null,544),[[y,m.search]]),u(t("select",{"onUpdate:modelValue":e[2]||(e[2]=s=>m.promo_type=s),class:"filter-select",onChange:j},e[25]||(e[25]=[t("option",{value:""},"Все типы",-1),t("option",{value:"percent"},"Процент",-1),t("option",{value:"fixed"},"Фиксированный",-1)]),544),[[N,m.promo_type]]),u(t("select",{"onUpdate:modelValue":e[3]||(e[3]=s=>m.is_active=s),class:"filter-select",onChange:j},e[26]||(e[26]=[t("option",{value:"true"},"Активные",-1),t("option",{value:"false"},"Выключенные",-1),t("option",{value:""},"Все (вкл. выключенные)",-1)]),544),[[N,m.is_active]])]),E.value?(o(),F(Le,{key:0,description:E.value,size:"sm","show-retry":"",onRetry:C},null,8,["description"])):S("",!0),c(ze,{"aria-label":"Промокоды",columns:ae,data:re.value,isLoading:w.value||A.value,isEnd:I.value,loadMore:ue},{code:k(({row:s})=>[t("span",je,d(s.code),1)]),promo_type:k(({row:s})=>[c(q,{tone:s.promo_type==="percent"?"primary":"info",label:s.promo_type==="percent"?"Процент":"Фиксированный"},null,8,["tone","label"])]),value:k(({row:s})=>[s.promo_type==="percent"?(o(),n("span",Ge,d(s.value)+"%",1)):(o(),n("span",He,d(B(s.value)),1))]),usage:k(({row:s})=>[f(d(s.used_count)+" / "+d(s.usage_limit??"∞"),1)]),period:k(({row:s})=>[t("span",Je,[f(d(L(s.valid_from))+" ",1),s.valid_until?(o(),n("span",Xe," → "+d(L(s.valid_until)),1)):(o(),n("span",Ke," → ∞"))])]),bound_user:k(({row:s})=>[t("span",Qe,d(s.bound_user_login??"Все"),1)]),status:k(({row:s})=>
1[c(q,{tone:ne[s.status]??"neutral",label:oe[s.status]??String(s.status)},null,8,["tone","label"])]),actions:k(({row:s})=>[t("div",Ye,[u((o(),n("button",{class:"action-btn action-btn--neutral",onClick:$(b=>xe(s),["stop"])},[c(v(Ve),{size:13})],8,et)),[[p,"История активаций"]]),u((o(),n("button",{class:J(["action-btn",s.is_active?"action-btn--warning":"action-btn--success"]),onClick:$(b=>pe(s),["stop"])},[(o(),F($e(s.is_active?v(Ae):v(Ie)),{size:13}))],10,tt)),[[p,s.is_active?"Деактивировать":"Активировать"]]),u((o(),n("button",{class:"action-btn action-btn--danger",onClick:$(b=>ce(s),["stop"])},[c(v(Ee),{size:13})],8,st)),[[p,"Удалить"]])])]),_:1},8,["data","isLoading","isEnd"]),r.open?(o(),n("div",{key:1,class:"modal-overlay",onClick:e[17]||(e[17]=$(s=>r.open=!1,["self"]))},[t("div",lt,[t("div",it,[e[27]||(e[27]=t("h3",{class:"modal__title"},"Создать промокод",-1)),t("button",{class:"modal__close",onClick:e[4]||(e[4]=s=>r.open=!1)},[c(v(O),{size:18})])]),t("div",ot,[t("div",nt,[t("div",at,[e[28]||(e[28]=t("label",{class:"field__label"},[f("Код "),t("span",{class:"req"},"*")],-1)),u(t("input",{"onUpdate:modelValue":e[5]||(e[5]=s=>i.code=s),type:"text",class:"field__input",maxlength:"32",placeholder:"PROMO2026",onInput:e[6]||(e[6]=s=>i.code=i.code.toUpperCase())},null,544),[[y,i.code]])]),t("div",dt,[e[30]||(e[30]=t("label",{class:"field__label"},[f("Тип "),t("span",{class:"req"},"*")],-1)),u(t("select",{"onUpdate:modelValue":e[7]||(e[7]=s=>i.promo_type=s),class:"field__select"},e[29]||(e[29]=[t("option",{value:"percent"},"Процент (кэшбэк %)",-1),t("option",{value:"fixed"},"Фиксированный (бонус ₽)",-1)]),512),[[N,i.promo_type]])])]),t("div",rt,[t("div",ut,[t("label",_t,[e[31]||(e[31]=f(" Значение ")),e[32]||(e[32]=t("span",{class:"req"},"*",-1)),t("span",pt,d(i.promo_type==="percent"?"% (≤100)":"₽"),1)]),u(t("input",{"onUpdate:modelValue":e[8]||(e[8]=s=>i.value=s),type:"number",min:"0.01",max:i.promo_type==="percent"?100:void 0,step:"0.01",class:"field__input",placeholder:"10"},null,8,ct),[[y,i.value]])]),t("div",mt,[e[33]||(e[33]=t("label",{class:"field__label"},[f("Макс. скидка ₽ "),t("span",{class:"field__hint-inline"},"необяз.")],-1)),u(t("input",{"onUpdate:modelValue":e[9]||(e[9]=s=>i.max_discount_rub=s),type:"number",min:"0",step:"0.01",class:"field__input",placeholder:"Без ограничения"},null,512),[[y,i.max_discount_rub]])])]),t("div",vt,[t("div",ft,[e[34]||(e[34]=t("label",{class:"field__label"},[f("Лимит использований "),t("span",{class:"field__hint-inline"},"пусто = ∞")],-1)),u(t("input",{"onUpdate:modelValue":e[10]||(e[10]=s=>i.usage_limit=s),type:"number",min:"1",class:"field__input",placeholder:"∞"},null,512),[[y,i.usage_limit]])]),t("div",bt,[e[35]||(e[35]=t("label",{class:"field__label"},"Лимит на юзера",-1)),u(t("input",{"onUpdate:modelValue":e[11]||(e[11]=s=>i.per_user_limit=s),type:"number",min:"1",class:"field__input",placeholder:"1"},null,512),[[y,i.per_user_limit]])])]),t("div",yt,[t("div",gt,[e[36]||(e[36]=t("label",{class:"field__label"},[f("Активен с "),t("span",{class:"field__hint-inline"},"пусто = сейчас")],-1)),u(t("input",{"onUpdate:modelValue":e[12]||(e[12]=s=>i.valid_from=s),type:"datetime-local",class:"field__input"},null,512),[[y,i.valid_from]])]),t("div",ht,[e[37]||(e[37]=t("label",{class:"field__label"},[f("Активен до "),t("span",{class:"field__hint-inline"},"пусто = бессрочно")],-1)),u(t("input",{"onUpdate:modelValue":e[13]||(e[13]=s=>i.valid_until=s),type:"datetime-local",class:"field__input"},null,512),[[y,i.valid_until]])])]),t("div",xt,[e[38]||(e[38]=t("label",{class:"field__label"},[f(" Персональный код для юзера "),t("span",{class:"field__hint-inline"},"UUID пользователя или поиск по логину")],-1)),t("div",kt,[u(t("input",{"onUpdate:modelValue":e[14]||(e[14]=s=>U.value=s),type:"text",class:"field__input",placeholder:"Введите логин / email для поиска…",onInput:be},null,544),[[y,U.value]]),h.value.length>0?(o(),n("div",Ct,[(o(!0),n(R,null,X(h.value,s=>(o(),n("button",{key:s.id,class:"user-search-item",onClick:b=>ye(s)},[t("span",St,d(s.login),1),t("span",wt,d(s.id),1)],8,Ut))),128))])):S("",!0)]),i.bound_user_id?(o(),n("div",Tt,[t("span",null,d(U.value||i.bound_user_id),1),t("button",{class:"bound-user-chip__remove",onClick:ge},[c(v(O),{size:12})])])):S("",!0),e[39]||(e[39]=t("span",{class:"field__hint"},"Если не выбран — промокод публичный (для всех)",-1))]),t("div",Vt,[e[40]||(e[40]=t("label",{class:"field__label"},"Описание",-1)),u(t("input",{"onUpdate:modelValue":e[15]||(e[15]=s=>i.description=s),type:"text",class:"field__input",maxlength:"500",placeholder:"Необязательное описание"},null,512),[[y,i.description]])]),r.error?(o(),n("div",$t,d(r.error),1)):S("",!0)]),t("div",At,[t("button",{class:"btn btn--secondary",disabled:r.loading,onClick:e[16]||(e[16]=s=>r.open=!1)},"Отмена",8,It),t("button",{class:"btn btn--primary",disabled:!G.value||r.loading,onClick:he}
1,[r.loading?(o(),n("span",zt,"Создание…")):(o(),n("span",Dt,"Создать"))],8,Et)])])])):S("",!0),a.open?(o(),n("div",{key:2,class:"modal-overlay",onClick:e[20]||(e[20]=$(s=>a.open=!1,["self"]))},[t("div",Pt,[t("div",Bt,[t("h3",Lt,[e[41]||(e[41]=f("Активации: ")),t("code",Mt,d(a.code),1)]),t("button",{class:"modal__close",onClick:e[18]||(e[18]=s=>a.open=!1)},[c(v(O),{size:18})])]),t("div",Nt,[a.loading?(o(),n("div",Ft,[c(K),e[42]||(e[42]=t("span",null,"Загрузка…",-1))])):a.items.length>0?(o(),n(R,{key:1},[t("table",Ot,[e[43]||(e[43]=t("thead",null,[t("tr",null,[t("th",null,"Пользователь"),t("th",null,"Платёж"),t("th",null,"Скидка"),t("th",null,"Бонус"),t("th",null,"Отозван"),t("th",null,"Дата")])],-1)),t("tbody",null,[(o(!0),n(R,null,X(a.items,s=>(o(),n("tr",{key:s.id,class:J({"act-table__row--reverted":s.reverted_at})},[t("td",null,d(s.user_login??s.user_id),1),t("td",Rt,d(s.payment_id?s.payment_id.slice(0,8)+"…":"—"),1),t("td",qt,d(B(s.discount_rub)),1),t("td",Wt,d(B(s.bonus_credited_rub)),1),t("td",null,[s.reverted_at?(o(),F(q,{key:0,tone:"danger",label:"Отозван"})):(o(),n("span",Zt,"—"))]),t("td",null,d(L(s.created_at)),1)],2))),128))])]),a.total>a.items.length?(o(),n("div",jt," Показано "+d(a.items.length)+" из "+d(a.total),1)):S("",!0)],64)):(o(),n("p",Gt,"Активаций пока нет"))]),t("div",Ht,[t("button",{class:"btn btn--secondary",onClick:e[19]||(e[19]=s=>a.open=!1)},"Закрыть")])])])):S("",!0),c(Be,{visible:_.visible,title:"Удалить промокод",message:`Промокод «${_.code}» будет удалён из списка и перестанет действовать. Восстановить можно через фильтр «Выключенные».`,severity:"danger",loading:_.loading,"confirm-text":"Удалить",onConfirm:me,onCancel:e[21]||(e[21]=s=>_.visible=!1)},null,8,["visible","message","loading"]),c(De,{visible:v(z).visible,text:v(z).text,severity:v(z).severity,duration:5e3,"onUpdate:visible":e[22]||(e[22]=s=>v(z).visible=s)},null,8,["visible","text","severity"])])}}}),ps=Pe(Jt,[["__scopeId","data-v-1094cca3"]]);export{ps as default};

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.