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
2.9 KiB
JavaScript
2 lines
2.9 KiB
JavaScript
import{P as x}from"./PageBar-DP6LpIFv.js";import{E as P,a as _}from"./Spinner.vue_vue_type_style_index_0_lang-Q7UPdMbi.js";import{S}from"./SectionHead-BuisDFZg.js";import{P as k}from"./ProductCard-Cbfp9CSN.js";import{d,i as n,c,k as o,u as l,z as B,A as C,n as E,B as b,x as v,f as y,g as u,q as L,C as $,D as A,s as p,F,r as I,h as N,v as V,_ as D}from"./index-0lMAZRQB.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BCX5wlE-.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BKaF0fT-.js";import"./index-W8LzFWDq.js";import"./DialogVant.vue_vue_type_style_index_0_lang-DiDmrjDM.js";import"./cartStore-qaurfaGv.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-BlJivYzz.js";import"./classCallCheck-Tw9-kd3s.js";const q={class:"flex justify-center items-center empty"},z=d({__name:"EmptyState",props:{description:{},image:{}},setup(t){return(e,a)=>(n(),c("div",q,[o(l(P),{description:"موردی یافت نشد",image:t.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),H="/assets/favoritEmpty-CIK7qR49.svg",T=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(t,{emit:e}){const a=e,r=B(),s=u(null);return C(s,()=>{a("fetch")},{distance:50}),(i,m)=>(n(),c("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:E({paddingTop:t.padding||l(r).headerHeight+"px"}),ref_key:"scrollArea",ref:s},[b(i.$slots,"default"),o(_,{cls:"my-[10px]",spinning:t.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),t.flag?(n(),v(z,{key:0,image:l(H)},null,8,["image"])):y("",!0)],4))}});function j(){const t=$({totalPages:0,productList:[],flag:!1});return{productsData:t,getProducts:async(a,r=!1)=>{if(!r){a.value=!0;try{t.productList=await L.listProducts(),t.flag=t.productList.length<1}catch(s){console.log(s)}finally{a.value=!1}}}}}const G={class:"newest"},K={key:0,class:"newest__grid"},g=20,M=d({__name:"NewestView",setup(t){const{productsData:e,getProducts:a}=j(),r=u(!1),s=u(!1),i=u(g),m=N(()=>e.productList.slice(0,i.value));A(async()=>{await a(r,!1)});const h=async()=>{if(i.value<e.productList.length){i.value+=g;return}await a(s,!0)};return(R,Z)=>{const w=V("container");return n(),c("div",G,[o(x,{title:"جدیدترین محصولات","back-to":"home"}),o(_,{spinning:r.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[o(T,{class:"newest__scroll",loading:s.value,flag:l(e).flag,padding:"0px",onFetch:h},{default:p(()=>[o(w,{class:"newest__body"},{default:p(()=>[o(S,{title:"تازهها",subtitle:"آخرین افزودههای مجموعه"}),l(e).productList.length?(n(),c("div",K,[(n(!0),c(F,null,I(m.value,f=>(n(),v(k,{key:f.id,value:f},null,8,["value"]))),128))])):y("",!0)]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),it=D(M,[["__scopeId","data-v-62cb523e"]]);export{it as default};
|