DEPLOY-01: docker-compose.yml passed only DATABASE_URL and PORT to the api service, so JWT_SECRET, JWT_CUSTOMER_SECRET, OTP_MASTER_CODE and every SMS_TREZ_* variable were silently dropped in Docker. A deployed build would have used the development JWT fallback and would not have had the delivery master code at all, so the demo login would have failed with no obvious cause. All are now forwarded, defaulting to empty (which the code treats as unset); verified with `docker compose config`. TEST-01: test-sales-expert-roundtrip.cjs had localhost:3077 hardcoded and could only connect by accident. Now defaults to the repo's API_PORT. 33/33. DELIVERY.md documents env vars (names only), run/deploy commands, how migrations run inside the container, the verification results and the known issues. release/delivery contains both parity branches with no conflicts (fast-forward). build 5/5, jest 45/45, admin smoke 43/43, apps smoke 43/43, B2B scan 34/34, B2B writes 25/25, auth-smoke 32/32, typecheck clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 lines
11 KiB
JavaScript
2 lines
11 KiB
JavaScript
import{d as T,g as F,H as M,D as Q,i as y,c as k,w as j,J as ee,b as c,e as N,f as E,F as A,r as te,x as U,y as q,K as se,G as ne,v as K,k as a,s as v,I as H,t as V,u as s,M as ae,E as W,C as B,q as P,N as oe,h as le,_ as z}from"./index-gDBsh1na.js";import{P as G}from"./PageBar-lc_J1EFz.js";import{_ as ue}from"./NotifyVant.vue_vue_type_script_setup_true_lang-04nlwBMZ.js";import{a as J,F as x,I as $,T as ie}from"./index-DcqagChw.js";import{a as re}from"./Spinner.vue_vue_type_style_index_0_lang-iladsJNR.js";import{_ as ce}from"./DialogVant.vue_vue_type_style_index_0_lang-CjJCtcu_.js";import"./FormItemContext-brdJVOto.js";import"./classCallCheck-Cn_U7yJ4.js";import"./_commonjsHelpers-Cpj98o6Y.js";const de={class:"otp-single-input"},pe=["type","placeholder","disabled"],me={key:0},ve=["innerHTML"],fe=T({__name:"SingleOtpInput",props:{inputType:{default:"tel"},value:{},separator:{},focus:{type:Boolean},inputClasses:{},shouldAutoFocus:{type:Boolean},isLastChild:{type:Boolean},placeholder:{},disabled:{type:Boolean}},emits:["on-change","on-keydown","on-paste","on-focus","on-blur"],setup(o,{emit:g}){const r=o,f=g,n=F(r.value||""),l=F(null),u=()=>(n.value=n.value.toString(),n.value.length>1&&(n.value=n.value.slice(0,1)),f("on-change",n.value)),h=d=>d>=48&&d<=57||d>=96&&d<=105,p=d=>{r.disabled&&d.preventDefault();const m=d||window.event,I=m.which?m.which:m.keyCode;h(I)||[8,9,13,37,39,46,86].includes(I)?f("on-keydown",d):m.preventDefault()},e=d=>f("on-paste",d),b=()=>(l.value.select(),f("on-focus")),i=()=>f("on-blur");return M(()=>r.value,(d,m)=>{d!==m&&(n.value=d??"")}),M(()=>r.focus,(d,m)=>{m!==d&&l.value&&r.focus&&(l.value.focus(),l.value.select())}),Q(()=>{l.value&&r.focus&&r.shouldAutoFocus&&(l.value.focus(),l.value.select())}),(d,m)=>(y(),k("div",de,[j(c("input",{type:o.inputType,placeholder:o.placeholder,disabled:o.disabled,ref_key:"input",ref:l,min:"0",max:"9",maxlength:"1",pattern:"[0-9]","onUpdate:modelValue":m[0]||(m[0]=I=>n.value=I),class:N(o.inputClasses),onInput:u,onKeydown:p,onPaste:e,onFocus:b,onBlur:i},null,42,pe),[[ee,n.value]]),!o.isLastChild&&o.separator?(y(),k("span",me,[c("span",{innerHTML:o.separator},null,8,ve)])):E("",!0)]))}}),he={class:"flex ltr justify-around w-full"},_e=8,ye=37,ge=39,be=46,we=T({__name:"OtpInput",props:{defaultFocus:{type:Boolean},numInputs:{default:4},separator:{},inputClasses:{},inputType:{},shouldAutoFocus:{type:Boolean,default:!1},placeholder:{},disabled:{type:Boolean,default:!1}},emits:["on-change","on-complete"],setup(o,{emit:g}){const r=o,f=g,n=F(0),l=F([]),u=F([]),h=t=>{r.defaultFocus&&t<r.numInputs&&!l.value[t]?n.value=l.value.length:n.value=t},p=()=>{n.value=-1},e=()=>l.value.join("").length===r.numInputs?f("on-complete",l.value.join("")):"Wait until the user enters the required number of characters",b=t=>{n.value=Math.max(Math.min(r.numInputs-1,t),0)},i=()=>b(n.value+1),d=()=>b(n.value-1),m=t=>{u.value=Object.assign([],l.value),typeof t=="string"&&t===""?l.value.splice(n.value,1):l.value[n.value]=t,u.value.join("")!==l.value.join("")&&(f("on-change",l.value.join("")),e())},I=t=>{var L;t.preventDefault();const w=(((L=t.clipboardData)==null?void 0:L.getData("text/plain"))??"").slice(0,r.numInputs-n.value).split("");if(r.inputType==="number"&&!w.join("").match(/^\d+$/))return"Invalid pasted data";const S=l.value.slice(0,n.value).concat(w);return S.slice(0,r.numInputs).forEach((Y,Z)=>{l.value[Z]=Y}),b(S.slice(0,r.numInputs).length),e()},R=t=>{m(t),i()},_=t=>{switch(t.keyCode){case _e:t.preventDefault(),m(""),d();break;case be:t.preventDefault(),m("");break;case ye:t.preventDefault(),d();break;case ge:t.preventDefault(),i();break}};return(t,O)=>(y(),k("div",null,[c("div",he,[(y(!0),k(A,null,te(o.numInputs,(w,D)=>(y(),U(fe,{key:D,focus:n.value===D,value:l.value[D],separator:o.separator,"input-type":o.inputType,"input-classes":o.inputClasses,"is-last-child":D===o.numInputs-1,"should-auto-focus":o.shouldAutoFocus,placeholder:o.placeholder,disabled:o.disabled,onOnChange:R,onOnKeydown:_,onOnPaste:I,onOnFocus:S=>h(D),onOnBlur:p},null,8,["focus","value","separator","input-type","input-classes","is-last-child","should-auto-focus","placeholder","disabled","onOnFocus"]))),128))])]))}}),ke=o=>` مقدار ${o} نا معتبر است `,X=o=>({pattern:/^(\+98|0098|98|0)?9\d{9}$/g,message:ke(o)}),C=o=>({required:!0,message:` لطفا ${o} را وارد کنید `}),Oe={class:"auth"},Ie={class:"auth__intro"},xe={class:"auth__mark","aria-hidden":"true"},Ce={class:"auth__sub"},Fe={class:"auth__card"},$e={key:0,class:"auth__timer"},De={key:1,class:"auth__timer"},Be=["disabled"],Te={class:"auth__switch"},Ee=T({__name:"LoginView",emits:["register"],setup(o,{emit:g}){const r=g,f=q(),n=se(),l=ne(),u=B({username:void 0}),h=B({show:!1,text:"اطلاعات کاربری در سیستم وجود ندارد."}),p=B({step:1,loading:!1,defaultFocus:!1}),e=F(0),b=()=>{e.value>0&&setTimeout(()=>{e.value>0&&(e.value-=1,b())},1e3)},i=async()=>{try{p.loading=!0,await P.requestOtp(String(u.username??"")),p.step=2,e.value=120,b(),await oe(()=>{p.defaultFocus=!0})}catch(_){const t=_ instanceof Error&&/\(429\)/.test(_.message)?m(_):null;h.text=t??"خطا در ارسال کد. لطفاً دوباره تلاش کنید.",h.show=!0}finally{p.loading=!1}},d=async _=>{try{p.loading=!0;const{token:t,customer:O}=await P.verifyOtp(String(u.username??""),_);l.login(t,O.id,O.mobile);const w=typeof n.query.redirect=="string"?n.query.redirect:void 0;await f.push(w??{name:"home"}),h.text="با موفقیت وارد شدید",h.show=!0}catch(t){h.text=t instanceof Error&&/\(429\)/.test(t.message)?m(t)??"تعداد تلاشها بیش از حد مجاز است.":"کد وارد شده صحیح نیست",h.show=!0}finally{p.loading=!1}};function m(_){const t=_.message.match(/\{.*\}/);if(!t)return null;try{const O=JSON.parse(t[0]);return typeof O.message=="string"?O.message:null}catch{return null}}const I=_=>_<10?"0"+_:_,R=le(()=>p.step===1?"دریافت رمز عبور":"دریافت مجدد رمز عبور");return(_,t)=>{const O=K("container");return y(),k("div",Oe,[a(ue,{timeOut:2e3,modelValue:h.show,"onUpdate:modelValue":t[0]||(t[0]=w=>h.show=w),text:h.text,color:"background-color: #DC2626"},null,8,["modelValue","text"]),a(G,{title:"ورود","back-to":"home"}),a(O,{class:"auth__body"},{default:v(()=>[c("section",Ie,[c("div",xe,[a(H,{icon:"vuesax-linear:security-user",size:"28"})]),t[3]||(t[3]=c("h2",{class:"auth__title"},"ورود به منتزر",-1)),c("p",Ce,V(p.step===1?"شماره موبایل خود را وارد کنید":"رمز یکبارمصرف را وارد کنید"),1)]),c("section",Fe,[p.step===2?(y(),k(A,{key:0},[a(we,{class:"auth__otp","input-classes":"otp-input",inputType:"tel","num-inputs":4,"should-auto-focus":!0,defaultFocus:p.defaultFocus,onOnComplete:d},null,8,["defaultFocus"]),e.value>0?(y(),k("p",$e," امکان دریافت مجدد رمز در "+V(I(e.value))+" ثانیه دیگر ",1)):(y(),k("p",De,"برای دریافت رمز عبور مجدد تلاش کنید"))],64)):E("",!0),a(s(J),{model:u,layout:"vertical",onFinish:i,class:"auth__form"},{default:v(()=>[j(a(s(x),{name:"username",label:"تلفن همراه",rules:[s(C)("تلفن همراه"),s(X)("تلفن همراه")]},{default:v(()=>[a(s($),{type:"number",value:u.username,"onUpdate:value":t[1]||(t[1]=w=>u.username=w)},null,8,["value"])]),_:1},8,["rules"]),[[ae,p.step===1]]),c("button",{type:"submit",class:N(["auth__cta",{"is-loading":p.loading}]),disabled:p.loading||e.value>0&&p.step===2},V(R.value),11,Be)]),_:1},8,["model"])]),c("p",Te,[t[4]||(t[4]=W(" اگر ثبت نام نکردهاید ",-1)),c("button",{type:"button",onClick:t[2]||(t[2]=w=>r("register",!0))},"ثبت نام کنید")])]),_:1})])}}}),Re=z(Ee,[["__scopeId","data-v-c130183b"]]),Se="/assets/registerDelay-BdXluE_Y.svg",Ve={class:"auth"},Ue={class:"auth__intro"},Ae={class:"auth__mark","aria-hidden":"true"},Le={class:"auth__card"},Me={class:"auth__switch"},Pe=["src"],je=T({__name:"RegisterView",emits:["register"],setup(o,{emit:g}){const r=g,f=q(),n=B({loading:!1}),l=F(!1),u=B({fname:void 0,lname:void 0,mobile:void 0,store_name:void 0,phone:void 0,address:void 0,city:void 0}),h=async()=>{try{n.loading=!0,l.value=!0}finally{n.loading=!1}};return(p,e)=>{const b=K("container");return y(),k("div",Ve,[a(G,{title:"ثبت نام","back-to":"home"}),a(re,{spinning:n.loading,tip:"در حال ثبت اطلاعات"},{default:v(()=>[a(b,{class:"auth__body"},{default:v(()=>[c("section",Ue,[c("div",Ae,[a(H,{icon:"vuesax-linear:user-add",size:"28"})]),e[10]||(e[10]=c("h2",{class:"auth__title"},"ساخت حساب کاربری",-1)),e[11]||(e[11]=c("p",{class:"auth__sub"},"اطلاعات فروشگاه خود را وارد کنید",-1))]),c("section",Le,[a(s(J),{model:u,layout:"vertical",onFinish:h,class:"auth__form"},{default:v(()=>[a(s(x),{name:"fname",label:"نام",rules:s(C)("نام")},{default:v(()=>[a(s($),{value:u.fname,"onUpdate:value":e[0]||(e[0]=i=>u.fname=i)},null,8,["value"])]),_:1},8,["rules"]),a(s(x),{name:"lname",label:"نام خانوادگی",rules:s(C)("نام خانوادگی")},{default:v(()=>[a(s($),{value:u.lname,"onUpdate:value":e[1]||(e[1]=i=>u.lname=i)},null,8,["value"])]),_:1},8,["rules"]),a(s(x),{name:"mobile",label:"شماره موبایل",rules:[s(X)("شماره موبایل"),s(C)("شماره موبایل")]},{default:v(()=>[a(s($),{value:u.mobile,"onUpdate:value":e[2]||(e[2]=i=>u.mobile=i),type:"number"},null,8,["value"])]),_:1},8,["rules"]),a(s(x),{name:"store_name",label:"نام فروشگاه",rules:s(C)("نام فروشگاه")},{default:v(()=>[a(s($),{value:u.store_name,"onUpdate:value":e[3]||(e[3]=i=>u.store_name=i)},null,8,["value"])]),_:1},8,["rules"]),a(s(x),{name:"phone",label:"تلفن فروشگاه",rules:[s(C)("تلفن فروشگاه")]},{default:v(()=>[a(s($),{value:u.phone,"onUpdate:value":e[4]||(e[4]=i=>u.phone=i),type:"number"},null,8,["value"])]),_:1},8,["rules"]),a(s(x),{name:"address",label:"آدرس پستی",rules:s(C)("آدرس")},{default:v(()=>[a(s(ie),{value:u.address,"onUpdate:value":e[5]||(e[5]=i=>u.address=i),rows:3},null,8,["value"])]),_:1},8,["rules"]),a(s(x),{name:"city",label:"شهر",rules:s(C)("شهر")},{default:v(()=>[a(s($),{value:u.city,"onUpdate:value":e[6]||(e[6]=i=>u.city=i)},null,8,["value"])]),_:1},8,["rules"]),e[12]||(e[12]=c("button",{type:"submit",class:"auth__cta"},"ثبت اطلاعات",-1))]),_:1},8,["model"])]),c("p",Me,[e[13]||(e[13]=W(" اگر حساب کاربری دارید ",-1)),c("button",{type:"button",onClick:e[7]||(e[7]=i=>r("register",!1))},"وارد شوید")])]),_:1})]),_:1},8,["spinning"]),a(ce,{timeOut:-1,show:l.value,"onUpdate:show":e[9]||(e[9]=i=>l.value=i),closeOnClickOverlay:!1},{img:v(()=>[c("img",{src:s(Se),alt:"",class:"opacity-80"},null,8,Pe)]),title:v(()=>[...e[14]||(e[14]=[c("div",{class:"p-5"}," ثبت نام شما با موفقیت انجام شد. منتظر تایید اطلاعات ثبت نامی شما توسط کارشناسان بمانید. ",-1)])]),button:v(()=>[c("div",{class:"text-center",onClick:e[8]||(e[8]=i=>s(f).push({name:"home"}))},"متوجه شدم")]),_:1},8,["show"])])}}}),Ne=z(je,[["__scopeId","data-v-23baea3e"]]),Ze=T({__name:"LoginRegisterView",setup(o){const g=F(!1),r=f=>g.value=f;return(f,n)=>(y(),k(A,null,[g.value?E("",!0):(y(),U(Re,{key:0,onRegister:r})),g.value?(y(),U(Ne,{key:1,onRegister:r})):E("",!0)],64))}});export{Ze as default};
|