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>
2 lines
4.2 KiB
JavaScript
2 lines
4.2 KiB
JavaScript
import{d as z,o as S,c,k as a,s as d,u as w,g as r,q as N,i,b as s,F as P,r as B,I as u,t as o,f as m,v as D,e as F,_ as I}from"./index-0lMAZRQB.js";import{P as E}from"./PageBar-DP6LpIFv.js";import{a as R}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S as $}from"./SearchInput-BoLb-2jQ.js";import{D as U}from"./index-BlJivYzz.js";import{P as q}from"./index-CWibuKdZ.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-Tw9-kd3s.js";const L={class:"cch"},M={class:"cch__barExtra"},O={key:0,class:"cch__list"},T=["onClick"],j={class:"cch__head"},A={class:"cch__name"},G={class:"cch__facts"},H={class:"cch__fact"},J={dir:"ltr"},K={class:"cch__fact"},Q={dir:"ltr"},W={key:0,class:"cch__fact"},X={key:1,class:"cch__empty"},Y={key:2,class:"cch__empty"},Z={key:0,class:"cch__detail"},ss={class:"cch__detailTitle"},es={class:"cch__rows"},ts={class:"cch__row"},os={dir:"ltr"},as={class:"cch__row"},ls={dir:"ltr"},ns={class:"cch__row"},cs={class:"cch__row"},is={class:"cch__row"},rs={dir:"ltr"},_s={class:"cch__row"},ds={dir:"ltr"},us={class:"cch__row"},vs=z({__name:"CustomerChoiceView",setup(hs){const _=r([]),v=r(!1),y=r(!1),h=r(!1),b=r(null),p=r(!1),l=r(null);function g(n){const e=Number(n??0);return Number.isFinite(e)?e.toFixed(3):"0.000"}async function f(){v.value=!0,h.value=!1;try{_.value=await N.getExpertCustomers(b.value)}catch{h.value=!0,_.value=[]}finally{v.value=!1}}async function k(n){b.value=n!=null&&n.trim()?n.trim():null,await f()}async function C(){await f(),y.value=!1}function x(n){l.value=n,p.value=!0}return S(f),(n,e)=>{const V=D("container");return i(),c("div",L,[a(E,{title:"لیست مشتریان","back-to":"userPage::hasSubRoute"},{below:d(()=>[s("div",M,[a($,{onSearch:k,"place-holder":"جستجو"})])]),_:1}),a(R,{spinning:v.value&&!_.value.length,tip:"درحال دریافت اطلاعات"},{default:d(()=>[a(w(q),{modelValue:y.value,"onUpdate:modelValue":e[0]||(e[0]=t=>y.value=t),onRefresh:C},{default:d(()=>[a(V,{class:"cch__body"},{default:d(()=>[_.value.length?(i(),c("div",O,[(i(!0),c(P,null,B(_.value,t=>(i(),c("article",{key:t.id,class:"cch__card",onClick:ps=>x(t)},[s("div",j,[s("h3",A,o(t.name),1),s("span",{class:F(["cch__state",t.active===1?"is-on":"is-off"])},o(t.active===1?"فعال":"غیرفعال"),3)]),s("div",G,[s("div",H,[a(u,{icon:"vuesax-linear:mobile",size:"15"}),s("span",J,o(t.mobile||"—"),1)]),s("div",K,[a(u,{icon:"vuesax-linear:call",size:"15"}),s("span",Q,o(t.phone||"—"),1)]),t.store_name?(i(),c("div",W,[a(u,{icon:"vuesax-linear:shop",size:"15"}),s("span",null,o(t.store_name),1)])):m("",!0)])],8,T))),128))])):!v.value&&!h.value?(i(),c("section",X,[a(u,{icon:"vuesax-linear:profile-2user",size:"26"}),s("p",null,o(b.value?"مشتری با این مشخصات پیدا نشد.":"هنوز مشتریای به شما معرفی نشده است."),1)])):m("",!0),h.value?(i(),c("section",Y,[a(u,{icon:"vuesax-linear:danger",size:"26"}),e[3]||(e[3]=s("p",null,"دریافت اطلاعات با خطا روبهرو شد.",-1)),s("button",{type:"button",class:"cch__retry",onClick:f},"تلاش دوباره")])):m("",!0)]),_:1})]),_:1},8,["modelValue"])]),_:1},8,["spinning"]),a(w(U),{open:p.value,"onUpdate:open":e[2]||(e[2]=t=>p.value=t),placement:"bottom",height:"auto",closable:!1,"body-style":{padding:"0"}},{default:d(()=>[l.value?(i(),c("div",Z,[s("h2",ss,o(l.value.name),1),s("dl",es,[s("div",ts,[e[4]||(e[4]=s("dt",null,"موبایل",-1)),s("dd",os,o(l.value.mobile||"—"),1)]),s("div",as,[e[5]||(e[5]=s("dt",null,"تلفن",-1)),s("dd",ls,o(l.value.phone||"—"),1)]),s("div",ns,[e[6]||(e[6]=s("dt",null,"نام مغازه",-1)),s("dd",null,o(l.value.store_name||"—"),1)]),s("div",cs,[e[7]||(e[7]=s("dt",null,"نام پاساژ",-1)),s("dd",null,o(l.value.pasazh_name||"—"),1)]),s("div",is,[e[8]||(e[8]=s("dt",null,"سقف اعتبار",-1)),s("dd",rs,o(g(l.value.gram_level))+" گرم",1)]),s("div",_s,[e[9]||(e[9]=s("dt",null,"بدهی گرمی",-1)),s("dd",ds,o(g(l.value.remain))+" گرم",1)]),s("div",us,[e[10]||(e[10]=s("dt",null,"وضعیت",-1)),s("dd",null,o(l.value.active===1?"فعال":"غیرفعال"),1)])]),s("button",{type:"button",class:"cch__close",onClick:e[1]||(e[1]=t=>p.value=!1)},"بستن")])):m("",!0)]),_:1},8,["open"])])}}}),xs=I(vs,[["__scopeId","data-v-0f43a8be"]]);export{xs as default};
|