Files
tehran_taj/apps/user-app-v2/dist/assets/HomeView-B075G2-B.js
T
s.esmaeiliandClaude Opus 5 5ad1083aee parity(apps+api): complete_profile in both apps [ref: henza_server Major/CustomerController::complete]
Ports "تکمیل پروفایل" end to end (D22).

API
- POST customer/me/complete-profile — three required document ids, the
  customer taken from the token, verification step set to the reference's
  LIVE value (approved outright; its `= 1` line is commented out at :83 in
  favour of `= 2` at :85). Both SMS messages byte-identical and non-blocking
  per D20.
- POST customer/me/documents — the reference let the app upload through the
  same file/create the admin used, inside its auth:api-customer group
  (routes/api.php:95); the target's copy is admin-guarded, so the page could
  not have uploaded at all. Reuses AdminUploadsService unchanged, so both
  paths share one size limit, MIME whitelist and naming scheme (UPL-01).
- PROFILE_ADMIN_MOBILES replaces the reference's four hardcoded personal
  numbers; blank means nobody is notified and the upload still succeeds.

Three reference behaviours deliberately NOT ported, all in ISSUES.md:
- SEC-14: `$customer->update($request->all())` mass-assigned the whole request
  body, letting the app write its own credit limit, making charge, gold debt,
  active flag or mobile. Replaced with a three-field whitelist.
- SEC-15: four real personal mobiles hardcoded in the source.
- APP-03: refresh()'s unterminated setInterval page reload.

Apps (both, template+script byte-identical, per-app styling only)
- CompleteProfileView + SingleImageUploader
- route /complete_profile, redirecting home once the documents are in, as the
  reference's guard did (router/index.ts:266)
- the entry point on the profile screen, shown only while they are missing
  (profile.vue:96-102)

Also (D23): JWT_CUSTOMER_SECRET now warns loudly at boot when unset. It falls
back to JWT_SECRET, which signs app and admin tokens with the same key and
leaves the `typ` check as the only barrier — and an expert's app token carries
their AdminUser id in `sub`. Warn rather than refuse to boot (D19, lowest
risk); DELIVERY.md lists it as the first pre-release step (REL-03).

Verified: build 5/5 · jest 45/45 · complete-profile 38/38 (new) ·
expert login 36/36 · apps smoke 43/43 · admin smoke 43/43 ·
B2B scan 34 ok/0 broken · typecheck clean on all four apps.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 01:42:07 +03:30

2 lines
11 KiB
JavaScript

import{_ as se}from"./Spinner.vue_vue_type_style_index_0_lang-Ce4r_sA4.js";import{d as X,o as ee,a as ae,c as r,b as _,F as D,r as F,e as C,f as o,g as h,h as O,n as B,i as V,_ as q,j as N,t as G,I as j,k as oe,w as le,u as $,l as S,m as ie,p as W,q as re,s as L,L as Y,v as ce,x as ue}from"./index-D7u32dbn.js";import{u as de,S as ve}from"./SingleProduct-BYO4_Jip.js";import{R as _e}from"./RateStrip-BlU2EbWJ.js";import{u as pe}from"./cartStore-B3Iy7abs.js";import{P as me}from"./index-B7hk2Rd_.js";import{D as fe}from"./index-CGMkzVe8.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-I8IV1V1D.js";import"./index-CnhrxceM.js";import"./DialogVant.vue_vue_type_style_index_0_lang-CVN0TLHx.js";import"./dialogEmpty1-Caw7F5KL.js";import"./filters-CLL9nGZ2.js";import"./classCallCheck-BIPEroH2.js";const ge={key:0,class:"hero"},he=["onClick"],ye=["src","alt"],ke={key:1,class:"hero__artFallback","aria-hidden":"true"},Ie={key:0,class:"hero__dots"},be=["aria-label","onClick"],K=46,$e=.76,Pe=36.6,Se=.75,we=X({__name:"HeroCarousel",props:{slides:{},autoplay:{type:Boolean,default:!0}},emits:["select"],setup(u,{emit:k}){const p=u,P=k,v=h(0),m=h(null),d=h(!1),c=h(0);let I=0,f=null,g;const l=O(()=>p.slides.length);function x(e){let s=e-v.value;l.value>2&&(s>l.value/2&&(s-=l.value),s<-l.value/2&&(s+=l.value));const i=d.value?c.value:0,t=Math.abs(s),n=s*Pe+i,w=s===0?1:$e,y=t>1?0:t===0?1:Se;return{transform:`translate3d(${n}%, 0, 0) scale(${w})`,opacity:String(y),zIndex:String(10-t),pointerEvents:t>1?"none":"auto",transition:d.value?"none":"transform .42s cubic-bezier(.22,.61,.36,1), opacity .42s ease"}}function b(e){v.value=(e%l.value+l.value)%l.value,a()}function R(){b(v.value+1)}function T(){b(v.value-1)}function A(e){var s,i;l.value<2||(d.value=!0,I=e.clientX,c.value=0,f=e.pointerId,(i=(s=e.currentTarget).setPointerCapture)==null||i.call(s,e.pointerId),H())}function M(e){var i;if(!d.value||e.pointerId!==f)return;const s=((i=m.value)==null?void 0:i.clientWidth)||1;c.value=(e.clientX-I)/s*100}function E(e){if(!d.value)return;const s=e.clientX-I;d.value=!1,c.value=0,f=null,s>K?T():s<-K?R():a()}function z(e,s){if(!(Math.abs(c.value)>1)){if(e!==v.value){b(e);return}P("select",s)}}function H(){g&&clearInterval(g),g=void 0}function a(){H(),p.autoplay&&l.value>1&&(g=setInterval(R,6e3))}return ee(a),ae(H),(e,s)=>u.slides.length?(o(),r("section",ge,[_("div",{class:"hero__stage",ref_key:"stage",ref:m,onPointerdown:A,onPointermove:M,onPointerup:E,onPointercancel:E},[(o(!0),r(D,null,F(u.slides,(i,t)=>(o(),r("article",{key:i.key,class:V(["hero__card",{"is-active":t===v.value}]),style:B(x(t)),onClick:n=>z(t,i)},[i.image?(o(),r("img",{key:0,src:i.image,alt:i.title,class:"hero__art",draggable:"false"},null,8,ye)):(o(),r("div",ke))],14,he))),128))],544),u.slides.length>1?(o(),r("div",Ie,[(o(!0),r(D,null,F(u.slides,(i,t)=>(o(),r("button",{key:i.key,type:"button",class:V(["hero__dot",{"is-active":t===v.value}]),"aria-label":i.title,onClick:n=>b(t)},null,10,be))),128))])):C("",!0)])):C("",!0)}}),Ce=q(we,[["__scopeId","data-v-48cbe7d5"]]),xe={class:"cats no-scrollbar"},Ee=["onClick"],He={class:"cats__mark","aria-hidden":"true"},Le=["src"],Oe={class:"cats__title"},Re=X({__name:"CategoryGrid",props:{categories:{},activeId:{}},emits:["select"],setup(u,{emit:k}){const p=k;return(P,v)=>(o(),r("div",xe,[(o(!0),r(D,null,F(u.categories,m=>{var d;return o(),r("button",{key:m.id,type:"button",class:V(["cats__tile",{"is-active":m.id===u.activeId}]),onClick:c=>p("select",m)},[_("span",He,[(d=m.icon)!=null&&d.image?(o(),r("img",{key:0,src:m.icon.image,alt:""},null,8,Le)):(o(),N(j,{key:1,icon:"vuesax-linear:3d-cube-scan",size:"27"}))]),_("span",Oe,G(m.title),1)],10,Ee)}),128))]))}}),Me=q(Re,[["__scopeId","data-v-aef04be0"]]),ze={class:"panel__art"},Be=["alt"],De={class:"panel__title"},Te={class:"panel__meta"},Ae={class:"panel__weight"},Ue={key:0,class:"panel__wageOld"},Ge={class:"panel__wage"},Ne=X({__name:"ProductPanel",props:{value:{},wageBefore:{}},emits:["open"],setup(u,{emit:k}){const p=u,P=k,{image:v,title:m,min_gram:d,wage:c}=pe(p.value);function I(f){return f%1===0?String(f):f.toFixed(2)}return(f,g)=>{const l=oe("lazy");return o(),r("article",{class:"panel",onClick:g[0]||(g[0]=x=>P("open",u.value))},[_("div",ze,[le(_("img",{alt:$(m)},null,8,Be),[[l,$(v)]])]),_("h3",De,G($(m)),1),_("div",Te,[_("span",Ae,G($(d))+" گرم",1),$(c)!=null?(o(),r(D,{key:0},[g[1]||(g[1]=_("span",{class:"panel__sep","aria-hidden":"true"},null,-1)),u.wageBefore!=null?(o(),r("span",Ue,"اجرت "+G(I(u.wageBefore))+"٪",1)):C("",!0),_("span",Ge,G(I($(c)))+"٪ اجرت",1)],64)):C("",!0)])])}}}),te=q(Ne,[["__scopeId","data-v-4f623012"]]),Fe={class:"reel"},Ve=["onClick"],Xe={class:"reel__allMark","aria-hidden":"true"},Q=46,qe=.78,Z=92.5,We=.62,Ye=X({__name:"ProductCarousel",props:{products:{}},emits:["open","all"],setup(u,{emit:k}){const p=u,P=k,v=h(0),m=h(null),d=h(!1),c=h(0);let I=0,f=null;const g=O(()=>[...p.products.map(a=>({key:a.id,kind:"product",product:a})),{key:"__all__",kind:"all"}]),l=O(()=>g.value.length);function x(a){let e=a-v.value;l.value>2&&(e>l.value/2&&(e-=l.value),e<-l.value/2&&(e+=l.value));const s=d.value?c.value:0,i=e*Z+s,t=Math.min(Math.abs(e+s/Z),1),n=1-(1-qe)*t,w=1-(1-We)*t,y=Math.abs(e)<=1,U=y?w:0;return{transform:`translate3d(${i}%, 0, 0) scale(${n})`,opacity:String(U),zIndex:String(10-Math.abs(e)),pointerEvents:y?"auto":"none",transition:d.value?"none":"transform .55s cubic-bezier(.21,1.02,.36,1), opacity .45s ease"}}function b(a){v.value=(a%l.value+l.value)%l.value}function R(){b(v.value+1)}function T(){b(v.value-1)}function A(a){var e,s;l.value<2||(d.value=!0,I=a.clientX,c.value=0,f=a.pointerId,(s=(e=a.currentTarget).setPointerCapture)==null||s.call(e,a.pointerId))}function M(a){var s;if(!d.value||a.pointerId!==f)return;const e=((s=m.value)==null?void 0:s.clientWidth)||1;c.value=(a.clientX-I)/e*100}function E(a){if(!d.value)return;const e=a.clientX-I;d.value=!1,c.value=0,f=null,e>Q?T():e<-Q&&R()}function z(a,e){if(!(Math.abs(c.value)>1)){if(a!==v.value){b(a);return}P("open",e)}}function H(a){if(!(Math.abs(c.value)>1)){if(a!==v.value){b(a);return}P("all")}}return(a,e)=>(o(),r("section",Fe,[_("div",{class:"reel__stage",ref_key:"stage",ref:m,onPointerdown:A,onPointermove:M,onPointerup:E,onPointercancel:E},[(o(!0),r(D,null,F(g.value,(s,i)=>(o(),r("div",{key:s.key,class:V(["reel__cell",{"is-active":i===v.value}]),style:B(x(i))},[s.kind==="product"?(o(),N(te,{key:0,value:s.product,onOpen:t=>z(i,t)},null,8,["value","onOpen"])):(o(),r("button",{key:1,type:"button",class:"reel__all",onClick:t=>H(i)},[_("span",Xe,[S(j,{icon:"vuesax-linear:arrow-left-2",size:"26"})]),e[0]||(e[0]=_("span",{class:"reel__allText"},"مشاهده همه محصولات جدید",-1))],8,Ve))],6))),128))],544)]))}}),je=q(Ye,[["__scopeId","data-v-b79ea2a7"]]),Je="/assets/shipping-and-delivery-CyUGL93q.png",Ke="/assets/sports-and-competition-ao926_SX.png",ne="/assets/montzar-logo-05_bmbid.png",Qe=[{type:"popup",src:Je,text:"ارسال سریع و مطمئن سفارش‌های شما به سراسر کشور.",link:void 0},{type:"popup",src:Ke,text:"جدیدترین محصولات منتزر را در بخش محصولات جدید ببینید.",link:void 0},{type:"popup",src:ne,text:"منتزر، همراه شما در خرید و فروش طلا.",link:void 0}],Ze=ie("config",{state:()=>({config:{main_slider:Qe},cats:[],loaded:!1}),actions:{setCats(u){this.cats=u},async init(){try{const u=await W.listProducts(),k=new Map;for(const p of u)p.category&&!k.has(p.category.id)&&k.set(p.category.id,{id:p.category.id,title:p.category.title,icon:{image:ne}});this.cats=[...k.values()],this.loaded=!0}catch(u){console.log(u)}}}}),et={class:"home"},tt={class:"home__bar"},nt={class:"home__barInner"},st={class:"home__list"},at={key:3,class:"home__empty"},ot=70,lt=6,it=4,rt=X({__name:"HomeView",setup(u){let k=!1;const p=ue(),P=Ze(),v=de(),m=h(!0),d=h(!1),c=h([]),I=h(null),f=h(null),g=h(!1),l=h(null),x=h(k);function b(t){return{"--reveal-delay":`${t*ot}ms`}}const R=O(()=>c.value),T=O(()=>c.value.slice(0,lt)),A=O(()=>c.value.slice(0,it)),M=O(()=>{var t;return(t=f.value)!=null&&t.length?f.value.filter(n=>n.image).map((n,w)=>({key:`${w}-${n.image}`,title:"",image:n.image,link:n.link||void 0})):P.cats.slice(0,5).map(n=>({key:n.id,title:n.title,image:E(n.id),categoryId:n.id}))});function E(t){var w,y;const n=c.value.find(U=>{var J;return((J=U.category)==null?void 0:J.id)===t});return(y=(w=n==null?void 0:n.images)==null?void 0:w[0])==null?void 0:y.url}function z(t){l.value=t.id,g.value=!0}function H(t){v.query.cats=[t.id],p.push({name:"search"})}function a(t){if(t.link){/^https?:\/\//i.test(t.link)?window.open(t.link,"_blank","noopener"):p.push(t.link);return}t.categoryId&&(v.query.cats=[t.categoryId]),p.push({name:"search"})}function e(){p.push({name:"newestProduct"})}async function s(){try{const[t]=await Promise.all([W.listProducts(),P.init()]);c.value=t}catch(t){console.log(t)}try{I.value=await W.getLatestGoldPrice()}catch{I.value=null}try{f.value=await W.getHomeSlider()}catch{f.value=null}}async function i(){await s(),d.value=!1}return ee(async()=>{await s(),m.value=!1,!x.value&&(await re(),requestAnimationFrame(()=>{x.value=!0,k=!0}))}),(t,n)=>{const w=ce("container");return o(),r("div",et,[_("header",tt,[_("div",nt,[n[3]||(n[3]=_("img",{src:se,alt:"منتزر",class:"home__logo"},null,-1)),S(_e,{quote:I.value,compact:"",class:"home__rate"},null,8,["quote"])])]),S($(me),{modelValue:d.value,"onUpdate:modelValue":n[0]||(n[0]=y=>d.value=y),onRefresh:i},{pulling:L(()=>[S($(Y),{size:"18"})]),loosing:L(()=>[S($(Y),{size:"18"})]),loading:L(()=>[S($(Y),{size:"18"})]),success:L(()=>[...n[4]||(n[4]=[_("span",null,null,-1)])]),default:L(()=>[S(w,{class:V(["home__body",{"is-revealed":x.value}])},{default:L(()=>[M.value.length?(o(),N(Ce,{key:0,slides:M.value,class:"home__hero home__reveal",style:B(b(0)),onSelect:a},null,8,["slides","style"])):C("",!0),$(P).cats.length?(o(),r("section",{key:1,class:"home__section home__reveal",style:B(b(1))},[n[5]||(n[5]=_("h2",{class:"home__heading"},"دسته بندی ها",-1)),S(Me,{categories:$(P).cats,"active-id":null,onSelect:H},null,8,["categories"])],4)):C("",!0),R.value.length?(o(),r("section",{key:2,class:"home__section home__reveal",style:B(b(2))},[n[6]||(n[6]=_("h2",{class:"home__heading"},"محصولات جدید",-1)),S(je,{products:T.value,onOpen:z,onAll:e},null,8,["products"]),_("div",st,[(o(!0),r(D,null,F(A.value,(y,U)=>(o(),N(te,{key:y.id,value:y,class:"home__reveal",style:B(b(3+U)),onOpen:z},null,8,["value","style"]))),128))])],4)):C("",!0),!m.value&&!c.value.length?(o(),r("section",at,[S(j,{icon:"vuesax-linear:box",size:"26"}),n[7]||(n[7]=_("p",null,"هنوز محصولی در مجموعه ثبت نشده است.",-1))])):C("",!0)]),_:1},8,["class"])]),_:1},8,["modelValue"]),S($(fe),{visible:g.value,"onUpdate:visible":n[2]||(n[2]=y=>g.value=y),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:L(()=>[l.value?(o(),N(ve,{key:0,id:l.value,onCloseDrawer:n[1]||(n[1]=y=>g.value=!1)},null,8,["id"])):C("",!0)]),_:1},8,["visible"])])}}}),$t=q(rt,[["__scopeId","data-v-89790e42"]]);export{$t as default};