PageSourceSearch

https://colara.co/assets/Vendors-BC-PVKoC.js

js colara.co collected 2026-10-02 01:23:31 UTC 104,155 bytes, 12 lines download raw bytes

1import{r as n,j as e}from"./vendor-Dz9lJ0A9.js";import{a as Ls}from"./date-utils-VPArwFdR.js";import{a as Ta,b as Aa,D as qa,c as Ra,S as Oa,h as La,d as Ma,P as _a,u as Ka,C as Ua}from"./dnd-kit-VU3KNzIT.js";import{H as Ba}from"./HelpTooltip-ZxgTx8XV.js";import{a as Ms,u as Qa,b as za,c as Wa,d as Ha}from"./use-vendors-Dhpglr84.js";import{u as Ga}from"./use-dismissed-hints-CS8gEuUL.js";import{Q as re,e as B,f as Q,av as Bt,K as A,m as F,S as Ya,C as Ee,W as dt,y as Fe,af as pt,am as Ja,P as U,B as C,a0 as ee,ab as Ie,aD as Xa,a1 as te,a2 as se,a3 as ae,L as X,U as lt,R as Ue,M as Za,ep as en,X as Qt,dK as Lt,a4 as _s,a5 as Es,a as tn,h as Ks,ac as sn,N as Us,aH as an,F as ct,a9 as nn,Y as Mt,E as Ke,al as rn,ag as on,at as Fs,V as dn,aS as ln,aB as cn}from"./index-BDOD5E4V.js";import{B as J}from"./badge-DV7OMou0.js";import{P as xt}from"./phone-BYLo2hRo.js";import{I as zt}from"./instagram-D3wahxJq.js";import{P as mn}from"./PreferredVendorPicker-DXdxx9VC.js";import{C as mt}from"./checkbox-CKtbmYQK.js";import{c as qt,a as un}from"./vendor-category-NmEdqf1O.js";import{I as O}from"./input-uKcRzRZU.js";import{S as pn}from"./search-_0AhvJvF.js";import{a as xn}from"./use-page-edit-permission-CML5S_Fz.js";import{R as hn}from"./ReadOnlyBanner-CbncLEIt.js";import{u as gn,F as Rt}from"./field-error-Cyx61sdP.js";import{u as Bs}from"./use-money-COqRa-gb.js";import{E as fn}from"./empty-state-BuhuU5ze.js";import{L as T}from"./label-xakz0IwZ.js";import{S as tt,a as st,b as at,c as nt,d as Re}from"./select-BqpPFFZ7.js";import{S as Qs}from"./switch-CTKr17l3.js";import{T as rt}from"./textarea-B6S3DUiX.js";import{A as zs}from"./AiWritingAssist-B2CsnXYN.js";import{P as jn}from"./PageHelper-DlLkbNgT.js";import{E as yn}from"./EmailPreviewModal-C1KlrKnj.js";import{u as Oe,M as Ds}from"./useSendEmail-VzJS3P-p.js";import{Q as vn}from"./QuickInsertButton-ChbX5o4q.js";import{S as bn}from"./SmsThread-BsiuRJZe.js";import{a as Le,b as Nn}from"./routes-CnUv5vQr.js";import{P as Ws}from"./pencil-Ct3hcvbE.js";import{u as wn}from"./use-ensure-wedding-id-url-CAkWqqLD.js";import{c as Me,a as Cn}from"./vendor-credits-Dt-P1Ogq.js";import{e as kn,T as Ot}from"./page-chrome-B_m6zO_M.js";import{C as Sn}from"./CopyToClientButton-Bts4u8A1.js";import{V as _t}from"./VendorCategoryOptions-D6dNso11.js";import{P as Kt}from"./plus-DXEHL3ds.js";import{a as Pn}from"./ShareWeddingDialog-BIGV1NY2.js";import{S as Hs}from"./star-eyEMRSoI.js";import{G as Wt}from"./globe-CyA4LPyI.js";import{L as $n}from"./lock-B6WKmd2G.js";import{U as Ts}from"./upload-BLxF6oWs.js";import{F as In}from"./file-spreadsheet-CRVS43wl.js";import{C as As}from"./circle-check-CJ_VUuj_.js";import{Z as Gs}from"./zap-BFvx7yl0.js";import{C as ut}from"./check-DtEZOD33.js";import{S as Ve}from"./send-D2ID-sFR.js";import{C as Vn}from"./chevron-right-DSIqreSQ.js";import{C as En}from"./copy-dUWtYfC2.js";import{B as Fn}from"./briefcase-Yqg0A39e.js";import{G as Dn}from"./grip-vertical-WdKeR_bN.js";import{S as Tn}from"./shield-BsFtER-O.js";import{T as An}from"./trash-2-DB6k7OfX.js";import{U as it}from"./user-jNm9qoKu.js";import{f as qn}from"./format-TE1zKFYr.js";import{P as Ys}from"./paperclip-C2dgC7YH.js";import{C as ot}from"./calendar-Djt6tY64.js";import{M as Ut}from"./map-pin-NOdPePnm.js";import{E as Rn}from"./eye-off-lB8x--i3.js";import{R as On}from"./rotate-ccw-DBoJyePA.js";import"./circle-question-mark-Bqs4yPi3.js";import"./use-undo-delete-Cmuf5YzP.js";import"./use-subscription-L5b-ZlfW.js";import"./demo-ids-9GOwPNZM.js";import"./platform-fee-BXS45kYa.js";import"./page-keys-CfdTyt9X.js";import"./timeline-plan-DMrHSBzv.js";import"./free-plan-galleries-DRlNoTXr.js";import"./free-tier-pages-BBb825GL.js";import"./WorkspaceTrialOffer-CtabjGYt.js";import"./currency-D2nl_7x3.js";import"./index-DiCFY80r.js";import"./index-DBElOBAj.js";import"./chevron-up-Cxk5DR03.js";import"./wand-sparkles-1lgr-9Q1.js";import"./framer-motion-B-6Peltb.js";import"./skeleton-Dp0qviHj.js";import"./EmailTemplatePicker-DQTQrg-h.js";import"./popover-DLgxV-6d.js";import"./list-BLP47b8F.js";import"./save-C1Cv7VS4.js";import"./braces-3gkFdW37.js";import"./crm-shortcodes-C9arKWs7.js";import"./client-name-DrkX_Dts.js";import"./TimelineRichEditor-CWcsB4h6.js";import"./purify.es-D7kaK67O.js";import"./use-upload-BhuNLqHD.js";import"./timeline-notes-BAXXUWUX.js";import"./list-ordered-q1jHSUws.js";import"./heading-2-CkGv6oen.js";import"./link-qDdbFJaq.js";import"./text-align-start-DRmXArhb.js";import"./image-CRRQUQpN.js";import"./link-2-DxAadr_f.js";import"./command-7zEmp0OB.js";import"./undo-2-DuE24aMz.js";import"./pen-line-BmI8eKDA.js";import"./mouse-pointer-click-DrhaqtWj.js";import"./clock-BGjkcAN7.js";import"./calendar-heart-DJ6dtsJ_.js";import"./layout-grid-D3ok2cOJ.js";import"./useInfiniteQuery-CNWotK0C.js";import"./ShortCodeReference-BmVZrmi6.js";import"./ShortCodePreviewDialog-DxThENJM.js";
1import"./EmailPreviewMergeBanner-B3PuzVt2.js";import"./use-prepend-scroll-DHh69URn.js";import"./community-forum-Cz56orCo.js";import"./installment-anchors-CUSqoQz9.js";import"./use-timeline-plan-26wpyIgg.js";import"./differenceInCalendarDays-CLfZenBU.js";import"./getTimezoneOffsetInMilliseconds-Dg5lkPpW.js";import"./use-debounced-value-BJebhLgm.js";import"./constants-Hyk7busR.js";import"./en-US-B1YEHn5a.js";(function(){try{var s=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{};s.SENTRY_RELEASE={id:"8dd115ac638cf6a2a2cf5668d0686c96509328ed"};var o=new s.Error().stack;o&&(s._sentryDebugIds=s._sentryDebugIds||{},s._sentryDebugIds[o]="8af91240-2804-4f67-a9d1-222da7d00c1f",s._sentryDebugIdIdentifier="sentry-dbid-8af91240-2804-4f67-a9d1-222da7d00c1f")}catch{}})();const Ln=new Set(["a","an","and","as","at","by","for","in","of","on","or","the","to","with"]);function $e(s){const o=s.trim(),d=[...o.matchAll(/[\p{L}\p{N}][\p{L}\p{M}\p{N}'’]*/gu)];let x=0;return o.replace(/[\p{L}\p{N}][\p{L}\p{M}\p{N}'’]*/gu,m=>{const N=x++;return m!==m.toLowerCase()||N>0&&N<d.length-1&&Ln.has(m)?m:m.replace(new RegExp("^([od]['’])?(\\p{L})","u"),(u,w,y)=>(w||"").toUpperCase()+y.toUpperCase())})}const Mn={selected:"Interested",dismissed:"Passed"};function qs(s){const o=s.find(d=>d.recommenderFirstName||d.recommenderLastName);return o?[o.recommenderFirstName,o.recommenderLastName].filter(Boolean).join(" "):"your planner"}function _n({weddingId:s,canRespond:o}){const{toast:d}=re(),x=n.useMemo(()=>["/api/vendor-recommendations",s],[s]),{data:m=[]}=B({queryKey:x,enabled:!!s}),N=Q({mutationFn:async({id:r,status:v})=>(await F("PATCH",`/api/vendor-recommendations/${r}/status`,{status:v})).json(),onSuccess:()=>A.refetchQueries({queryKey:x}),onError:r=>{d({title:"Couldn’t complete that",description:Bt(r),variant:"destructive"})}}),u=n.useRef(!1);if(n.useEffect(()=>{if(!o||u.current)return;const r=m.filter(v=>v.status==="pending");r.length!==0&&(u.current=!0,Promise.all(r.map(v=>F("PATCH",`/api/vendor-recommendations/${v.id}/status`,{status:"viewed"}))).then(()=>A.refetchQueries({queryKey:x})).catch(()=>{}))},[o,m,x]),!s||m.length===0)return null;const w=m.filter(r=>r.status!=="dismissed"),y=m.filter(r=>r.status==="dismissed"),k=o?[...w,...y]:m;return e.jsxs("div",{className:"mb-8","data-testid":"section-recommended-vendors",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(Ya,{className:"w-4 h-4 text-primary"}),e.jsx("h2",{className:"text-lg font-display font-light",children:o?"Recommended for you":"Recommended vendors"}),e.jsx(J,{variant:"secondary",className:"bg-primary/10 text-primary border-none",children:m.length})]}),e.jsx("p",{className:"text-sm text-muted-foreground mb-4",children:o?`${qs(m)} thinks these could be a great fit for your wedding.`:`Sent by ${qs(m)}. The couple's answers show below.`}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",children:k.map(r=>{const v=r.vendorWebsite&&/^https?:\/\//.test(r.vendorWebsite)?r.vendorWebsite:null,E=r.vendorInstagram?r.vendorInstagram.replace("@",""):null,p=Mn[r.status];return e.jsxs(Ee,{className:`hover-elevate transition-shadow duration-300 ${r.status==="dismissed"?"opacity-60":""}`,"data-testid":`card-recommendation-${r.id}`,children:[e.jsxs(dt,{className:"pb-3",children:[e.jsxs("div",{className:"flex justify-between items-start gap-2",children:[r.vendorCategory&&e.jsx(J,{variant:"secondary",className:"bg-primary/10 text-primary border-none no-default-hover-elevate no-default-active-elevate",children:r.vendorCategory}),p&&e.jsx(J,{variant:"outline","data-testid":`badge-recommendation-status-${r.id}`,children:p})]}),e.jsx("h3",{className:"text-base font-medium mt-2","data-testid":`text-recommendation-name-${r.id}`,children:r.vendorName}),r.vendorCompany&&e.jsx("p",{className:"text-sm text-muted-foreground",children:r.vendorCompany}),r.vendorLocation&&e.jsx("p",{className:"text-xs text-muted-foreground/80",children:r.vendorLocation})]}),e.jsxs(Fe,{className:"space-y-3",children:[r.message&&e.jsxs("p",{className:"text-sm italic text-muted-foreground",children:["“",r.message,"”"]}),r.vendorPriceRange&&e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Price range: ",r.vend
1orPriceRange]}),e.jsxs("div",{className:"flex flex-wrap gap-3 text-sm",children:[r.vendorEmail&&e.jsxs("a",{href:`mailto:${r.vendorEmail}`,className:"inline-flex items-center gap-1 text-primary hover:underline","data-testid":`link-recommendation-email-${r.id}`,children:[e.jsx(pt,{className:"w-3.5 h-3.5"})," Email"]}),r.vendorPhone&&e.jsxs("a",{href:`tel:${r.vendorPhone}`,className:"inline-flex items-center gap-1 text-primary hover:underline",children:[e.jsx(xt,{className:"w-3.5 h-3.5"})," ",r.vendorPhone]}),v&&e.jsxs("a",{href:v,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary hover:underline",children:[e.jsx(Ja,{className:"w-3.5 h-3.5"})," Website"]}),E&&e.jsxs("a",{href:`https://instagram.com/${E}`,target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-primary hover:underline",children:[e.jsx(zt,{className:"w-3.5 h-3.5"})," @",E]})]}),o&&e.jsxs("div",{className:"flex gap-2 pt-1",children:[e.jsx(U,{size:"sm",disabled:N.isPending||r.status==="selected",onClick:()=>N.mutate({id:r.id,status:"selected"}),"data-testid":`button-recommendation-interested-${r.id}`,children:r.status==="selected"?"Interested":"I'm interested"}),e.jsx(C,{variant:"outline",size:"sm",disabled:N.isPending,onClick:()=>N.mutate({id:r.id,status:r.status==="dismissed"?"viewed":"dismissed"}),"data-testid":`button-recommendation-pass-${r.id}`,children:r.status==="dismissed"?"Undo":"Not for us"})]})]})]},r.id)})})]})}function Kn({weddingId:s,vendorsQueryKey:o}){const{toast:d}=re(),[x,m]=n.useState(!1),[N,u]=n.useState(null),[w,y]=n.useState(new Set),{data:k=[],isLoading:r}=B({queryKey:["/api/referral-lists"],enabled:x}),{data:v,isLoading:E}=B({queryKey:["/api/referral-lists",N],enabled:x&&N!==null}),p=v?.items??[],P=p.filter(h=>!w.has(h.id)).map(h=>h.id),g=()=>{u(null),y(new Set)},S=Q({mutationFn:async()=>await(await F("POST",`/api/referral-lists/${N}/add-to-wedding`,{weddingId:s,itemIds:P})).json(),onSuccess:h=>{A.refetchQueries({queryKey:[o]});const f=h.skipped.length?` ${h.skipped.length} already on this wedding: ${h.skipped.join(", ")}.`:"";d({title:`${h.added} vendor${h.added===1?"":"s"} added`,description:`Imported onto this wedding.${f}`}),m(!1),g()},onError:h=>{d({title:"Couldn’t import the list",description:Bt(h),variant:"destructive"})}});return e.jsxs(ee,{open:x,onOpenChange:h=>{m(h),h||g()},children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(C,{variant:"outline",className:"tracking-wider uppercase text-xs","data-testid":"button-import-referral-list",children:[e.jsx(Xa,{className:"w-4 h-4 mr-2"}),"From Preferred Vendors"]})}),e.jsxs(te,{className:"max-w-lg max-h-[90vh] overflow-y-auto",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:N===null?"Import from a Preferred Vendors List":"Choose Who to Add"})}),N===null?e.jsxs("div",{className:"space-y-2 py-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Pick one of your Preferred Vendors lists and its vendors are added straight to this wedding."}),r?e.jsx("div",{className:"flex justify-center py-6",children:e.jsx(X,{className:"w-5 h-5 animate-spin text-muted-foreground"})}):k.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-6","data-testid":"text-no-referral-lists",children:"You haven’t built any Preferred Vendors lists yet. Create one under Vendor Network."}):e.jsx("div",{className:"space-y-1",children:k.map(h=>e.jsxs("button",{type:"button",onClick:()=>u(h.id),className:"w-full text-left px-3 py-2.5 rounded-md border border-border hover:bg-muted/50 transition-colors","data-testid":`button-pick-referral-list-${h.id}`,children:[e.jsx("p",{className:"text-sm font-medium",children:h.name}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[h.itemCount," vendor",h.itemCount===1?"":"s",h.description?` · ${h.description}`:""]})]},h.id))})]}):e.jsxs("div",{className:"space-y-3 py-2",children:[E?e.jsx("div",{className:"flex justify-center py-6",children:e.jsx(X,{className:"w-5 h-5 animate-spin text-muted-foreground"})}):e.jsx("div",{className:"space-y-1 max-h-[320px] overflow-y-auto",children:p.map(h=>e.jsxs("label",{className:"flex items-start gap-3 px-3 py-2 rounded-md hover:bg-muted/40 cursor-pointer","data-testid":`referral-item-${h.id}`,children:[e.jsx(mt,{checked:!w.has(h.id),onCheckedChange:f=>{const D=new Set(w);f?D.delete(h.id):D.add(h.id),y(D)},className:"mt-0.5","data-testid":`checkbox-referral-item-${h.id}`}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:h.name}),e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:[h.category||"Other",h.company?` · ${h.company}`:"",h.email?` · ${h.email}`:""]})]})]}
1,h.id))}),e.jsxs("div",{className:"flex justify-end gap-2 pt-1",children:[e.jsx(C,{variant:"outline",onClick:g,"data-testid":"button-referral-import-back",children:"Back"}),e.jsxs(U,{onClick:()=>S.mutate(),disabled:P.length===0||S.isPending||!s,"data-testid":"button-confirm-referral-import",children:[S.isPending&&e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"}),"Add ",P.length," to Wedding"]})]})]})]})]})}const Rs=s=>s.trim().toLowerCase();function Un({weddingId:s,vendorsQueryKey:o,existingNames:d}){const{toast:x}=re(),[m,N]=n.useState(!1),[u,w]=n.useState(""),[y,k]=n.useState(new Set),{data:r=[],isLoading:v}=B({queryKey:["/api/preferred-vendors"],enabled:m}),E=n.useMemo(()=>new Set(d.map(Rs)),[d]),p=n.useMemo(()=>{const f=u.trim().toLowerCase();return r.filter(D=>f?[D.name,D.company,D.category].some(L=>(L||"").toLowerCase().includes(f)):!0).slice().sort((D,L)=>qt(D.category).localeCompare(qt(L.category))||(D.name||"").localeCompare(L.name||""))},[r,u]),P=()=>{w(""),k(new Set)},g=(f,D)=>{k(L=>{const K=new Set(L);return D?K.add(f):K.delete(f),K})},S=Q({mutationFn:async()=>await(await F("POST","/api/preferred-vendors/bulk-add-to-wedding",{weddingId:s,vendorIds:Array.from(y)})).json(),onSuccess:f=>{A.refetchQueries({queryKey:[o]});const D=f.skipped.length?` ${f.skipped.length} already on this wedding: ${f.skipped.join(", ")}.`:"";x({title:`${f.added} vendor${f.added===1?"":"s"} added`,description:`Added from your Vendor Directory.${D}`}),N(!1),P()},onError:f=>{x({title:"Couldn’t add those vendors",description:Bt(f),variant:"destructive"})}});let h=null;return e.jsxs(ee,{open:m,onOpenChange:f=>{N(f),f||P()},children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(C,{variant:"outline",className:"tracking-wider uppercase text-xs","data-testid":"button-import-vendor-directory",children:[e.jsx(lt,{className:"w-4 h-4 mr-2"}),"From Vendor Directory"]})}),e.jsxs(te,{className:"max-w-lg max-h-[90vh] overflow-y-auto",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:"Add from Your Vendor Directory"})}),e.jsxs("div",{className:"space-y-3 py-1",children:[e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Everyone you have worked with is here. Pick who is on this wedding."}),e.jsxs("div",{className:"relative",children:[e.jsx(pn,{className:"w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"}),e.jsx(O,{value:u,onChange:f=>w(f.target.value),placeholder:"Search by name, company, or category",className:"pl-9","data-testid":"input-search-vendor-directory"})]}),v?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(X,{className:"w-5 h-5 animate-spin text-muted-foreground"})}):r.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-8","data-testid":"text-empty-vendor-directory",children:"Your directory is empty. It fills itself as you add vendors to weddings."}):p.length===0?e.jsxs("p",{className:"text-sm text-muted-foreground text-center py-8","data-testid":"text-no-directory-matches",children:["No one matches “",u.trim(),"”."]}):e.jsx("div",{className:"space-y-1 max-h-[340px] overflow-y-auto",children:p.map(f=>{const D=E.has(Rs(f.name||"")),L=qt(f.category),K=L!==h?L:null;return h=L,e.jsxs("div",{children:[K&&e.jsx("p",{className:"text-[11px] font-medium text-muted-foreground tracking-[0.12em] uppercase px-3 pt-3 pb-1",children:K}),e.jsxs("label",{className:`flex items-start gap-3 px-3 py-2 rounded-md ${D?"cursor-default":"hover:bg-muted/40 cursor-pointer"}`,"data-testid":`directory-vendor-${f.id}`,children:[e.jsx(mt,{checked:y.has(f.id),disabled:D,onCheckedChange:c=>g(f.id,c===!0),className:"mt-0.5","data-testid":`checkbox-directory-vendor-${f.id}`}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:`text-sm font-medium truncate ${D?"text-muted-foreground":""}`,children:f.name}),e.jsx("p",{className:"text-xs text-muted-foreground truncate",children:D?e.jsx("span",{"data-testid":`text-directory-already-${f.id}`,children:"Already on this wedding"}):e.jsxs(e.Fragment,{children:[f.company?`${f.company}`:f.email||"No contact details saved",f.weddingsCount?` · ${f.weddingsCount} wedding${f.weddingsCount===1?"":"s"}`:""]})})]})]})]},f.id)})}),e.jsxs("div",{className:"flex justify-end gap-2 pt-1",children:[e.jsx(C,{variant:"outline",onClick:()=>N(!1),"data-testid":"button-cancel-directory-import",children:"Cancel"}),e.jsxs(U,{onClick:()=>S.mutate(),disabled:y.size===0||S.isPending||!s,"data-testid":"button-confirm-directory-import",children:[S.isPending&&e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"}),"Add ",y.size," to Wedding"]})]})]})]})]})}
1function Bn({vendorId:s,vendorName:o}){const[d,x]=n.useState(!1),{weddingQueryParam:m}=Ue();return e.jsxs(e.Fragment,{children:[e.jsx(C,{variant:"ghost",size:"icon",onClick:()=>x(!0),title:"Text this vendor","data-testid":`button-text-vendor-${s}`,children:e.jsx(Za,{className:"w-4 h-4"})}),d&&e.jsx(ee,{open:d,onOpenChange:x,children:e.jsxs(te,{className:"max-w-lg",children:[e.jsx(se,{children:e.jsxs(ae,{children:["Text ",o]})}),e.jsx(bn,{threadUrl:`/api/vendors/${s}/sms${m}`,sendUrl:`/api/vendors/${s}/send-sms${m}`,readUrl:`/api/vendors/${s}/sms/read${m}`,invalidateKeys:[["/api/crm/inbox"]]})]})})]})}function Qn({currentWedding:s}){const{toast:o}=re(),{weddingQueryParam:d}=Ue(),[x,m]=n.useState(!1),[N,u]=n.useState(""),[w,y]=n.useState("");n.useEffect(()=>{u(s?.partner1Instagram||""),y(s?.partner2Instagram||"")},[s?.partner1Instagram,s?.partner2Instagram]);const k=Q({mutationFn:async p=>(await F("PATCH","/api/wedding-details/couple-instagram"+d,p)).json(),onSuccess:()=>{A.invalidateQueries({queryKey:["/api/wedding-details"+d]}),o({title:"Saved",description:"The couple's Instagram handles were updated."}),m(!1)},onError:()=>{o({title:"Couldn’t complete that",description:"Could not save the couple's handles. Try again.",variant:"destructive"})}}),r=s?.partner1Name||"Partner 1",v=s?.partner2Name||"Partner 2",E=!!(s?.partner1Instagram||s?.partner2Instagram);return x?e.jsxs("div",{className:"mb-4 p-3 rounded-md border space-y-3",children:[e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsxs(T,{htmlFor:"couple-ig-p1",className:"text-xs uppercase tracking-wider",children:[r," Instagram"]}),e.jsx(O,{id:"couple-ig-p1",value:N,onChange:p=>u(p.target.value),placeholder:"@yourname","data-testid":"input-couple-instagram-p1"})]}),e.jsxs("div",{children:[e.jsxs(T,{htmlFor:"couple-ig-p2",className:"text-xs uppercase tracking-wider",children:[v," Instagram"]}),e.jsx(O,{id:"couple-ig-p2",value:w,onChange:p=>y(p.target.value),placeholder:"@yourname","data-testid":"input-couple-instagram-p2"})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(U,{size:"compact",disabled:k.isPending,onClick:()=>k.mutate({partner1Instagram:N.trim()?N.trim():null,partner2Instagram:w.trim()?w.trim():null}),"data-testid":"button-save-couple-instagram",children:k.isPending?"Saving...":"Save"}),e.jsx(C,{variant:"outline",size:"sm",onClick:()=>{u(s?.partner1Instagram||""),y(s?.partner2Instagram||""),m(!1)},"data-testid":"button-cancel-couple-instagram",children:"Cancel"})]})]}):e.jsxs("div",{className:"mb-4 flex items-center justify-between gap-2 flex-wrap p-3 rounded-md border border-dashed",children:[e.jsxs("div",{className:"text-sm text-muted-foreground flex items-center gap-2",children:[e.jsx(zt,{className:"w-4 h-4"}),E?e.jsxs("span",{children:["Couple's Instagram:"," ",e.jsx("span",{className:"text-foreground font-medium","data-testid":"text-couple-handles-display",children:[s?.partner1Instagram,s?.partner2Instagram].filter(Boolean).join(" & ")})]}):e.jsx("span",{children:"Add the couple's Instagram handles so they appear at the top of the credits. Edit a vendor's handle on its own credit line below."})]}),e.jsx(C,{variant:"outline",size:"sm",className:"tracking-wider uppercase text-xs",onClick:()=>m(!0),"data-testid":"button-edit-couple-instagram",children:E?"Edit Couple":"Add Couple Handles"})]})}function zn(s){const o=s.trim();return o||null}function Os({vendor:s,categoryLabel:o,displayHandle:d,canEdit:x,selfProfile:m,onDismissSelf:N,field:u="instagram"}){const{toast:w}=re(),{weddingQueryParam:y}=Ue(),[k,r]=n.useState(!1),[v,E]=n.useState(""),p=(u==="instagram"?s.instagram:s.website)||"",P=()=>{E(p),r(!0)},g=()=>{E(p),r(!1)},S=u==="instagram"?"Instagram handle":"website",h=u==="instagram"?"Instagram handle":"website",f=u==="instagram"?"@handle":"https://…",D=u==="instagram"?s.isSelf?"Edit your brand Instagram":"Edit this vendor's Instagram":s.isSelf?"Edit your brand website":"Edit this vendor's website",L=Q({mutationFn:async V=>{const _=Nn(Le.vendors.update.path,{id:s.id})+y,z=await F(Le.vendors.update.method,_,{[u]:V});return Le.vendors.update.responses[200].parse(await z.json())},onSuccess:V=>
1{A.setQueryData([Le.vendors.list.path+y],_=>_&&_.map(z=>z.id===V.id?V:z)),A.invalidateQueries({queryKey:[Le.vendors.list.path+y]}),w({title:"Saved",description:`Vendor ${S} updated.`}),r(!1)},onError:()=>{w({title:"Couldn't complete that",description:`Could not save the vendor ${S}. Try again.`,variant:"destructive"})}}),K=Q({mutationFn:async V=>(await F("PUT","/api/planner-profile",{...m||{},[u]:V})).json(),onSuccess:()=>{A.invalidateQueries({queryKey:["/api/planner-profile"]}),w({title:"Saved",description:`Your brand ${h} was updated.`}),r(!1)},onError:()=>{w({title:"Couldn't complete that",description:`Could not save your ${h}. Try again.`,variant:"destructive"})}}),c=L.isPending||K.isPending,I=!!p,G=s.isSelf?"self":String(s.id),le=u==="instagram"?"credit-instagram":"credit-website",b=()=>{const V=u==="instagram"?Lt(v)||null:zn(v);s.isSelf?K.mutate(V):L.mutate(V)};if(k)return e.jsxs("div",{className:"flex flex-wrap items-center gap-2","data-testid":`${le}-edit-${G}`,children:[e.jsxs("span",{className:"text-sm",children:[o,":"]}),e.jsx(O,{value:v,onChange:V=>E(V.target.value),placeholder:f,className:`h-8 font-mono text-sm ${u==="website"?"w-56":"w-40"}`,autoFocus:!0,"data-testid":`input-${le}-${G}`,onKeyDown:V=>{V.key==="Enter"&&b(),V.key==="Escape"&&g()}}),e.jsx(U,{size:"compact",disabled:c,onClick:b,"data-testid":`button-save-${le}-${G}`,children:c?"Saving...":"Save"}),e.jsx(C,{variant:"outline",size:"sm",onClick:g,disabled:c,"data-testid":`button-cancel-${le}-${G}`,children:"Cancel"})]});const M=u==="website"&&I?e.jsx("a",{href:en(p),target:"_blank",rel:"noopener noreferrer",className:"underline text-foreground",children:s.name||d}):e.jsx("span",{className:I||u==="website"?void 0:"text-muted-foreground italic",children:d});return e.jsxs("div",{className:"flex items-center gap-2 group","data-testid":u==="instagram"?`text-credit-${G}`:`text-website-credit-${G}`,children:[e.jsxs("span",{className:"flex-1",children:[o,": ",M,s.isSelf&&e.jsx("span",{className:"ml-2 text-xs text-[#A8836F] font-sans not-italic","data-testid":u==="instagram"?"badge-self-credit":"badge-self-credit-web",children:"(you)"})]}),x&&e.jsx("button",{type:"button",onClick:P,className:"transition text-muted-foreground hover:text-foreground",title:D,"data-testid":`button-edit-${le}-${G}`,children:e.jsx(Ws,{className:"w-3 h-3"})}),s.isSelf&&N&&e.jsx("button",{type:"button",onClick:N,className:"transition text-muted-foreground hover:text-foreground",title:"Remove me from credits","data-testid":u==="instagram"?"button-dismiss-self-credit-social":"button-dismiss-self-credit-web",children:e.jsx(Qt,{className:"w-3 h-3"})})]})}function Wn({weddingQueryParam:s}){const[o,d]=n.useState(""),[x,m]=n.useState(""),{toast:N}=re(),{mutate:u,isPending:w}=Ms(),[y,k]=n.useState(!1),[r,v]=n.useState([]),[E,p]=n.useState(!1),[P,g]=n.useState(null),S=n.useRef(null),h=n.useRef(null),f=n.useCallback(async c=>{if(c.length<2){v([]),p(!1);return}try{const I=await F("GET",`/api/vendors/search?q=${encodeURIComponent(c)}`);if(I.ok){const G=await I.json();v(G),p(G.length>0)}}catch{v([])}},[]),D=c=>{d(c),h.current&&clearTimeout(h.current),h.current=setTimeout(()=>f(c),300)},L=c=>{d(c.name||""),c.category&&m(c.category),g({name:c.name||"",category:c.category||"",pointOfContact:c.pointOfContact||"",email:c.email||"",instagram:c.instagram||"",website:c.website||"",description:c.description||"",phone:c.phone||""}),p(!1),v([])};n.useEffect(()=>{const c=I=>{S.current&&!S.current.contains(I.target)&&p(!1)};return document.addEventListener("mousedown",c),()=>document.removeEventListener("mousedown",c)},[]);function K(){if(!o.trim()||!x)return;const c=P&&P.name===o.trim()?{...P,status:"approved"}:{name:o.trim(),category:x,status:"approved"};u(c,{onSuccess:()=>{N({title:"Vendor Added",description:`${o.trim()} has been added to your vendor list.`}),d(""),m(""),v([]),p(!1),k(!1),g(null)}})}return y?e.jsx(Ee,{className:"mb-6",children:e.jsx(Fe,{className:"py-4",children:e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-[180px] relative",ref:S,
1children:[e.jsx(T,{className:"text-xs text-muted-foreground mb-1 block",children:"Vendor Name"}),e.jsx(O,{value:o,onChange:c=>D(c.target.value),onFocus:()=>{r.length>0&&p(!0)},placeholder:"e.g. Dreamy Photography",onKeyDown:c=>{c.key==="Enter"&&o.trim()&&x&&K()},autoComplete:"off",autoFocus:!0,"data-testid":"input-quick-vendor-name"}),E&&r.length>0&&e.jsxs("div",{className:"absolute z-50 top-full left-0 right-0 mt-1 bg-popover border border-border rounded-md shadow-md max-h-48 overflow-y-auto","data-testid":"quick-add-vendor-suggestions",children:[e.jsx("p",{className:"text-[10px] tracking-wider uppercase text-muted-foreground px-3 pt-2 pb-1",children:"Vendors added by other couples"}),r.map((c,I)=>e.jsx("button",{type:"button",className:"w-full text-left px-3 py-2 hover-elevate flex items-center gap-2",onClick:()=>L(c),"data-testid":`quick-suggestion-vendor-${I}`,children:e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:c.name}),e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:[c.category,c.email?` · ${c.email}`:""]})]})},I))]})]}),e.jsxs("div",{className:"min-w-[160px]",children:[e.jsx(T,{className:"text-xs text-muted-foreground mb-1 block",children:"Category"}),e.jsxs(tt,{value:x,onValueChange:m,children:[e.jsx(st,{"data-testid":"select-quick-vendor-category",children:e.jsx(at,{placeholder:"Category"})}),e.jsx(nt,{children:e.jsx(_t,{})})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(U,{onClick:K,disabled:!o.trim()||!x||w,"data-testid":"button-quick-add-vendor",children:[w?e.jsx(X,{className:"w-4 h-4 animate-spin"}):e.jsx(Kt,{className:"w-4 h-4 mr-1"}),"Add"]}),e.jsx(C,{variant:"ghost",onClick:()=>{k(!1),d(""),m(""),v([]),p(!1)},"data-testid":"button-quick-add-cancel","aria-label":"Cancel",children:e.jsx(Qt,{className:"w-4 h-4"})})]})]})})}):e.jsx("div",{className:"mb-6",children:e.jsxs("button",{onClick:()=>k(!0),className:"w-full flex items-center gap-3 border border-dashed border-border rounded-md px-4 py-3 text-sm text-muted-foreground hover-elevate cursor-pointer transition-colors","data-testid":"button-quick-add-expand",children:[e.jsx(Kt,{className:"w-4 h-4"}),"Quick add a vendor..."]})})}function Hn({rating:s}){return e.jsx("span",{className:"flex items-center gap-0.5","aria-label":`${s} out of 5`,children:[1,2,3,4,5].map(o=>e.jsx(Hs,{className:`w-3.5 h-3.5 ${s>=o?"fill-amber-500 text-amber-500":"text-muted-foreground/40"}`},o))})}function Gn({profileId:s,vendorName:o,open:d,onOpenChange:x}){const{data:m=[],isLoading:N}=B({queryKey:["/api/vendor-profiles",s,"network-reviews"],queryFn:async()=>(await F("GET",`/api/vendor-profiles/${s}/network-reviews`)).json(),enabled:d});return e.jsx(ee,{open:d,onOpenChange:x,children:e.jsxs(te,{className:"max-w-lg","data-testid":"dialog-vendor-network-reviews",children:[e.jsxs(se,{children:[e.jsxs(ae,{className:"font-display text-xl font-normal",children:["What planners say about ",o]}),e.jsx(_s,{children:"Ratings other planners have chosen to share with the network. Nobody sees which wedding a rating came from."})]}),N?e.jsx("div",{className:"py-8 flex justify-center",children:e.jsx("div",{className:"w-5 h-5 border-2 border-primary/30 border-t-primary rounded-full animate-spin"})}):m.length===0?e.jsx("p",{className:"py-6 text-sm text-muted-foreground","data-testid":"text-network-reviews-empty",children:"No shared ratings yet. Ratings appear here once a planner shares one and the vendor has listed themselves in the directory."}):e.jsx("div",{className:"divide-y divide-border/40 max-h-[60vh] overflow-y-auto",children:m.map(u=>e.jsxs("div",{className:"py-4 space-y-2","data-testid":`row-network-review-${u.id}`,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Hn,{rating:u.rating}),e.jsx("span",{className:"text-sm font-medium",children:u.authorName}),u.isYours&&e.jsx("span",{className:"text-xs text-muted-foreground",children:"(yours)"})]}),u.content&&e.jsx("p",{className:"text-sm text-muted-foreground whitespace-pre-wrap",children:u.content}),u.reply&&e.jsxs("div",{className:"mt-2 pl-3 border-l-2 border-border/60",children:[e.jsxs("p",{className:"text-xs uppercase tracking-wide text-muted-foreground
1/80 mb-1",children:[o," replied"]}),e.jsx("p",{className:"text-sm text-muted-foreground whitespace-pre-wrap",children:u.reply.content})]})]},u.id))})]})})}function Yn({vendorId:s,weddingId:o,vendorName:d="this vendor"}){const{toast:x}=re(),[m,N]=n.useState(!1),{data:u=[]}=B({queryKey:["/api/vendor-reviews",o],queryFn:async()=>(await F("GET",`/api/vendor-reviews?weddingId=${o}`)).json(),enabled:!!o}),{data:w=[]}=B({queryKey:["/api/vendor-reviews/ratings"],queryFn:async()=>(await F("GET","/api/vendor-reviews/ratings")).json()}),{data:y=[]}=B({queryKey:["/api/vendor-reviews/network-ratings",o],queryFn:async()=>(await F("GET",`/api/vendor-reviews/network-ratings?weddingId=${o}`)).json(),enabled:!!o}),k=u.find(g=>g.vendorInfoId===s),r=k?w.find(g=>g.profileId===k.profileId):void 0,v=y.find(g=>g.vendorInfoId===s),E=Q({mutationFn:async g=>(await F("PUT",`/api/vendors/${s}/review`,{rating:g})).json(),onSuccess:()=>{A.invalidateQueries({queryKey:["/api/vendor-reviews",o]}),A.invalidateQueries({queryKey:["/api/vendor-reviews/ratings"]})},onError:g=>{x({title:"Couldn't save rating",description:Es(g),variant:"destructive"})}}),p=Q({mutationFn:async g=>(await F("PATCH",`/api/vendor-reviews/${k?.id}/share`,{shareScope:g})).json(),onSuccess:(g,S)=>{A.invalidateQueries({queryKey:["/api/vendor-reviews",o]}),A.invalidateQueries({queryKey:["/api/vendor-reviews/network-ratings",o]}),x({title:S==="network"?"Rating shared":"Rating made private",description:S==="network"?"Other planners can now see this rating and your business name. The vendor can reply to it.":"Only your team can see this rating now."})},onError:g=>{x({title:"Couldn't change sharing",description:Es(g),variant:"destructive"})}});if(!o)return null;const P=k?.shareScope==="network";return e.jsxs("div",{className:"flex items-center gap-1 pt-1","data-testid":`vendor-rating-${s}`,children:[[1,2,3,4,5].map(g=>e.jsx(C,{variant:"ghost",size:"icon",className:"h-6 w-6",disabled:E.isPending&&E.variables===g,onClick:()=>E.mutate(g),title:`Rate ${g} of 5`,"aria-label":`Rate ${g} of 5`,"aria-pressed":(k?.rating??0)>=g,"data-testid":`button-rate-vendor-${s}-${g}`,children:e.jsx(Hs,{className:`w-3.5 h-3.5 ${(k?.rating??0)>=g?"fill-amber-500 text-amber-500":"text-muted-foreground/50"}`})},g)),k&&e.jsxs(C,{variant:"ghost",size:"sm",className:"h-6 px-1.5 text-xs text-muted-foreground",disabled:p.isPending,onClick:()=>p.mutate(P?"private":"network"),title:P?"Shared with other planners. Click to make it private again.":"Only your team can see this. Click to share it with other planners.","aria-pressed":P,"data-testid":`button-share-rating-${s}`,children:[P?e.jsx(Wt,{className:"w-3 h-3 mr-1"}):e.jsx($n,{className:"w-3 h-3 mr-1"}),P?"Shared":"Private"]}),r&&r.reviewCount>1&&e.jsxs("span",{className:"text-xs text-muted-foreground ml-1","data-testid":`text-vendor-rating-history-${s}`,children:[r.averageRating," avg over ",r.reviewCount," weddings"]}),v&&v.reviewCount>0&&e.jsxs(e.Fragment,{children:[e.jsxs(C,{variant:"ghost",size:"sm",className:"h-6 px-1.5 text-xs text-muted-foreground underline underline-offset-2",onClick:()=>N(!0),"data-testid":`button-network-rating-${s}`,children:[v.averageRating," across ",v.reviewCount," shared"," ",v.reviewCount===1?"rating":"ratings"]}),e.jsx(Gn,{profileId:v.profileId,vendorName:d,open:m,onOpenChange:N})]})]})}function Jn({open:s,onOpenChange:o,weddings:d,vendorName:x,preferredPayload:m,onPickWedding:N,onSavedPreferredOnly:u}){const{toast:w}=re(),[y,k]=n.useState(!1),r=async()=>{k(!0);try{await F("POST","/api/preferred-vendors",m),A.invalidateQueries({queryKey:["/api/preferred-vendors"]}),w({title:"Saved to your Vendor Directory",description:`${m.name} is in your vendor rolodex. You can import them onto any wedding later.`}),o(!1),u()}catch{w({title:"Couldn't save vendor",description:"Something went wrong saving to your Vendor Directory. Please try again.",variant:"destructive"})}finally{k(!1)}};return e.jsx(ee,{open:s,onOpenChange:o,children:e.jsxs(te,{className:"max-w-md","data-testid":"dialog-vendor-wedding-picker",children:[e.jsxs(se,{children:[e.jsx(ae,{className:"font-display text-xl font-normal",children:"Where should this vendor go?"}),e.jsxs(_s,{children:["You're not viewing a specific wedding right now. Pick the wedding to add"," ",x?e.jsx("span",{className:"font-medium text-foreground",children:x}):"this vendor"," to, or save them to your Vendor Directory for later. Nothing you typed will be lost."]})]}),e.jsx("div",{className:"space-y-2 max-h-64 overflow-y-auto pr-1",children:d.map(v=>e.jsxs(C,{variant:"outline",className:"w-full justify-between gap-3",onClick:()=>{o(!1),N(v.id)},"data-testid":`button-pick-wedding-${v.id}`,children:[e.jsx("span",{className:"truncate",children:v.coupleNames||`Wedding #${v.id}`}),v.weddingDate&&e.jsx("span",{className:"text-xs text-muted-foreground shrink-0 font-normal",children:v.weddingDate})]},v.id))}),e.jsxs(C,{variant:"outline",className:"w-full",onClick:r,disabled:y,"data-testid":"button-save-preferred-only",children:[y?e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"}):e.jsx(lt,{className:"w-4 h-4 mr-2"}),"Save to Vendor Directory only"]})]})})}const Xn=[{key:"timeline",label:"Timeline",icon:ot},{key:"gallery",label:"Gallery",icon:Ut},{key:"vendors",label:"Vendors",icon:it},{key:"guest-info",label:"Guest Info",icon:it},{key:"documents",label:"Documents",icon:ct},{key:"checklist",label:"Checklist",icon:ut},{key:"messages",label:"Messages",icon:Ve},{key:"wedding-party",label:"Wedding Party",icon:it},{key:"budget",label:"Budget",icon:ot},{key:"seating",label:"Seating Chart",icon:Ut},{key:"gifts",label:"Gift Tracker",icon:ot},{key:"contacts",label:"Day-of Contacts",icon:xt},{key:"ai-timeline",label:"Timeline Builder",icon:Gs}];
1function Zn({vendor:s,open:o,onOpenChange:d,weddingQueryParam:x}){const{toast:m}=re(),N=cn(),{data:u}=B({queryKey:["/api/vendor-visibility",x],queryFn:async()=>(await F("GET",`/api/vendor-visibility${x}`)).json(),enabled:o}),{data:w,isLoading:y}=B({queryKey:["/api/vendor-access-overrides",s.id,x],queryFn:async()=>(await F("GET",`/api/vendor-access-overrides/${s.id}${x}`)).json(),enabled:o}),k=Q({mutationFn:async({pageKey:p,visible:P})=>(await F("PUT",`/api/vendor-access-overrides/${s.id}${x}`,{pageKey:p,visible:P})).json(),onSuccess:()=>{A.refetchQueries({queryKey:["/api/vendor-access-overrides",s.id,x]})},onError:p=>{m({title:"Couldn’t complete that",description:p.message,variant:"destructive"})}}),r=Q({mutationFn:async()=>(await F("DELETE",`/api/vendor-access-overrides/${s.id}${x}`)).json(),onSuccess:()=>{A.refetchQueries({queryKey:["/api/vendor-access-overrides",s.id,x]}),m({title:"Reset",description:"Vendor access reset to wedding defaults."})},onError:p=>{m({title:"Couldn’t complete that",description:p.message,variant:"destructive"})}});function v(p){const P=w?.find(S=>S.pageKey===p);return P?{visible:P.visible,isOverride:!0}:{visible:u?.find(S=>S.pageKey===p)?.visible??!1,isOverride:!1}}const E=w&&w.length>0;return e.jsx(ee,{open:o,onOpenChange:d,children:e.jsxs(te,{className:"max-w-md max-h-[85vh] overflow-y-auto","data-testid":"dialog-vendor-access",children:[e.jsxs(se,{children:[e.jsxs(ae,{children:["Access for ",s.name]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:"Control which pages this vendor can see. Changes override the wedding-wide defaults."})]}),y?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(X,{className:"w-6 h-6 animate-spin text-primary"})}):e.jsx("div",{className:"space-y-1 mt-2",children:Xn.map(p=>{const{visible:P,isOverride:g}=v(p.key),S=p.icon;return e.jsxs("div",{className:"flex items-center justify-between gap-3 py-2.5 px-3 rounded-lg hover-elevate","data-testid":`vendor-access-row-${p.key}`,children:[e.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[e.jsx("div",{className:`w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${P?"bg-primary/10":"bg-muted"}`,children:e.jsx(S,{className:`w-4 h-4 ${P?"text-primary":"text-muted-foreground"}`})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"text-sm font-medium",children:p.label}),g&&e.jsx(J,{variant:"outline",className:"ml-2 text-[10px] px-1.5 py-0 no-default-hover-elevate no-default-active-elevate",children:"Custom"})]})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[P?e.jsx(Ke,{className:"w-3.5 h-3.5 text-primary"}):e.jsx(Rn,{className:"w-3.5 h-3.5 text-muted-foreground"}),e.jsx(Qs,{checked:P,onCheckedChange:h=>k.mutate({pageKey:p.key,visible:h}),disabled:k.isPending,"data-testid":`vendor-access-switch-${p.key}`})]})]},p.key)})}),E&&e.jsx("div",{className:"border-t border-border pt-4 mt-4",children:e.jsxs(C,{variant:"outline",size:"sm",className:"w-full",onClick:async()=>{await N({title:"Reset this vendor's access?",description:`All custom page access for ${s.name} will be cleared and the wedding defaults will apply again. This can't be undone.`,confirmLabel:"Reset",testId:"confirm-reset-vendor-access"})&&r.mutate()},disabled:r.isPending,"data-testid":"button-reset-vendor-access",children:[r.isPending?e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"}):e.jsx(On,{className:"w-4 h-4 mr-2"}),"Reset to Wedding Defaults"]})}),e.jsx("p",{className:"text-xs text-muted-foreground text-center mt-2",children:"Pages without custom overrides follow the wedding-wide vendor visibility settings."})]})})}const _e={name:"",category:"",pointOfContact:"",email:"",instagram:"",website:"",description:"",phone:"",totalCost:"",depositAmount:"",amountPaid:"",paymentStatus:"unpaid",contractUrl:"",paymentDueDate:"",paymentNotes:""};function er(s){return`@${s.replace(/^@/,"")}`}function tr({vendor:s,canEdit:o,canEmail:d,canVendorEditOwn:x,setInviteVendor:m,setInviteMessage:N,setEmailVendor:u,setAccessVendor:w,openEditDialog:y,deleteVendor:k}){const{attributes:r,listeners:v,setNodeRef:E,transform:p,transition:P,isDragging:g}=Ka({id:s.id}),{formatCents:S}=Bs();return e.jsxs(Ee,{ref:E,className:`hover-elevate transition-shadow duration-300 ${g?"opacity-50 ring-2 ring-primary/30":""}`,style:{transform:Ua.Transform.toString(p),transition:P},"data-testid":`card-vendor-${s.id}`,children:[e.jsxs(dt,{className:"pb-3",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[o&&e.jsx("button",{...r,...v,className:"mt-0.5 p-1 text-muted-foreground
1/70 hover:text-muted-foreground cursor-grab active:cursor-grabbing shrink-0 touch-none",title:"Drag to reorder","data-testid":`drag-handle-vendor-${s.id}`,tabIndex:-1,children:e.jsx(Dn,{className:"w-3.5 h-3.5"})}),e.jsx("div",{className:"shrink-0",children:e.jsx(J,{variant:"secondary",className:"bg-primary/10 text-primary border-none no-default-hover-elevate no-default-active-elevate",children:s.category})})]}),(o||d||x(s))&&e.jsxs("div",{className:"flex flex-wrap justify-end gap-1",children:[d&&s.email&&e.jsxs(e.Fragment,{children:[e.jsx(C,{variant:"ghost",size:"icon",onClick:()=>{m(s),N("")},title:"Send profile invite","data-testid":`button-invite-vendor-${s.id}`,children:e.jsx(Us,{className:"w-4 h-4"})}),e.jsx(C,{variant:"ghost",size:"icon","aria-label":"Email vendor",onClick:()=>u(s),"data-testid":`button-email-vendor-${s.id}`,children:e.jsx(Ve,{className:"w-4 h-4"})})]}),d&&s.phone&&e.jsx(Bn,{vendorId:s.id,vendorName:s.name}),d&&e.jsx(C,{variant:"ghost",size:"icon",onClick:()=>w(s),title:"Manage vendor access","data-testid":`button-access-vendor-${s.id}`,children:e.jsx(Tn,{className:"w-4 h-4"})}),(o||x(s))&&e.jsxs(e.Fragment,{children:[e.jsx(C,{variant:"ghost",size:"icon","aria-label":"Edit",onClick:()=>y(s),"data-testid":`button-edit-vendor-${s.id}`,children:e.jsx(Ws,{className:"w-4 h-4"})}),o&&e.jsx(C,{variant:"ghost",size:"icon","aria-label":"Delete",onClick:()=>k(s.id),"data-testid":`button-delete-vendor-${s.id}`,children:e.jsx(An,{className:"w-4 h-4"})})]})]}),e.jsx(Mt,{className:"text-xl break-words","data-testid":`text-vendor-name-${s.id}`,children:s.name})]}),e.jsxs(Fe,{className:"space-y-2",children:[s.creditName&&s.creditName!==s.name&&e.jsxs("div",{className:"text-xs text-muted-foreground mb-1",children:["Credit as:"," ",e.jsx("span",{className:"font-medium text-foreground","data-testid":`text-vendor-credit-${s.id}`,children:s.creditName})]}),s.profileCompletedAt&&e.jsxs(J,{variant:"outline",className:"text-xs mb-1 no-default-hover-elevate no-default-active-elevate",children:[e.jsx(ut,{className:"w-3 h-3 mr-1"}),"Profile completed"]}),s.inviteSentAt&&!s.profileCompletedAt&&e.jsxs(J,{variant:"outline",className:"text-xs mb-1 text-muted-foreground no-default-hover-elevate no-default-active-elevate",children:["Invite sent ",Ls(s.inviteSentAt)]}),s.pointOfContact&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(it,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("span",{"data-testid":`text-vendor-poc-${s.id}`,children:s.pointOfContact})]}),s.email&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(pt,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("a",{href:`mailto:${s.email}`,className:"hover:underline truncate","data-testid":`text-vendor-email-${s.id}`,children:s.email})]}),s.phone&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(xt,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("span",{"data-testid":`text-vendor-phone-${s.id}`,children:s.phone})]}),s.instagram&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(zt,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("a",{href:`https://instagram.com/${s.instagram.replace(/^@/,"")}`,target:"_blank",rel:"noopener noreferrer",className:"hover:underline","data-testid":`text-vendor-instagram-${s.id}`,children:er(s.instagram)})]}),s.website&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(Wt,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("a",{href:s.website.startsWith("http")?s.website:`https://${s.website}`,target:"_blank",rel:"noopener noreferrer",className:"hover:underline truncate","data-testid":`text-vendor-website-${s.id}`,children:s.website.replace(/^https?:\/\//,"")})]}),s.description&&e.jsx("p",{className:"text-sm text-muted-foreground pt-1","data-testid":`text-vendor-desc-${s.id}`,children:s.description}),o&&e.jsx(Yn,{vendorId:s.id,weddingId:s.weddingId,vendorName:s.name}),(s.totalCost||s.paymentStatus&&s.paymentStatus!=="unpaid"||s.contractUrl)&&e.jsxs("div",{className:"border-t mt
1-3 pt-3 space-y-2",children:[s.totalCost!=null&&s.totalCost>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Total Cost"}),e.jsx("span",{className:"font-medium","data-testid":`text-vendor-cost-${s.id}`,children:S(s.totalCost)})]}),s.depositAmount!=null&&s.depositAmount>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Deposit"}),e.jsx("span",{"data-testid":`text-vendor-deposit-${s.id}`,children:S(s.depositAmount)})]}),s.amountPaid!=null&&s.amountPaid>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Paid"}),e.jsx("span",{className:"text-green-600 dark:text-green-400","data-testid":`text-vendor-paid-${s.id}`,children:S(s.amountPaid)})]}),s.totalCost!=null&&s.totalCost>0&&e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Balance"}),e.jsx("span",{className:`font-medium ${s.totalCost-(s.amountPaid||0)>0?"text-amber-600 dark:text-amber-400":"text-green-600 dark:text-green-400"}`,"data-testid":`text-vendor-balance-${s.id}`,children:S(s.totalCost-(s.amountPaid||0))})]}),s.paymentDueDate&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(dn,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsxs("span",{className:"text-muted-foreground",children:["Due: ",qn(new Date(s.paymentDueDate+"T00:00:00"),"MMM d, yyyy")]})]}),s.paymentStatus&&s.paymentStatus!=="unpaid"&&e.jsx(J,{variant:"outline",className:`text-xs no-default-hover-elevate no-default-active-elevate ${s.paymentStatus==="paid"?"border-green-400 text-green-700 dark:text-green-400 bg-green-50 dark:bg-green-950/20":s.paymentStatus==="deposit"?"border-blue-400 text-blue-700 dark:text-blue-400 bg-blue-50 dark:bg-blue-950/20":"border-amber-400 text-amber-700 dark:text-amber-400 bg-amber-50 dark:bg-amber-950/20"}`,"data-testid":`badge-vendor-payment-${s.id}`,children:s.paymentStatus==="paid"?"Paid in Full":s.paymentStatus==="deposit"?"Deposit Paid":s.paymentStatus==="partial"?"Partially Paid":"Unpaid"}),s.contractUrl&&e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(Ys,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("a",{href:s.contractUrl.startsWith("http")||s.contractUrl.startsWith("/")?s.contractUrl:`https://${s.contractUrl}`,target:"_blank",rel:"noopener noreferrer",className:"hover:underline text-[#A8836F] truncate","data-testid":`link-vendor-contract-${s.id}`,children:"View Contract"})]}),s.paymentNotes&&e.jsx("p",{className:"text-xs text-muted-foreground italic","data-testid":`text-vendor-payment-notes-${s.id}`,children:s.paymentNotes})]})]})]},s.id)}function ho(){const{data:s,isLoading:o}=Qa(),d=n.useMemo(()=>(s||[]).map(t=>({...t,name:$e(t.name)})),[s]),{formatCents:x,symbol:m}=Bs(),N=m.length>2?"pl-14":m.length>1?"pl-11":"pl-7",{data:u}=tn(),{user:w}=Ks(),y=gn(),{mutate:k,isPending:r}=Ms({setFieldErrors:y.setServerFieldErrors}),{mutate:v,isPending:E}=za(),{mutate:p}=Wa(),{mutate:P}=Ha(),[g,S]=n.useState(null),[h,f]=n.useState(null),D=Ta(Aa(_a,{activationConstraint:{distance:8}}));n.useEffect(()=>{S(null)},[d]);const L=n.useMemo(()=>{if(!g)return d;const t=new Map(g.map((a,i)=>[a,i]));return[...d].sort((a,i)=>(t.get(a.id)??d.length)-(t.get(i.id)??d.length))},[d,g]);function K(t){const{active:a,over:i}=t;if(f(null),!i||a.id===i.id)return;const l=L.map(be=>be.id),$=l.indexOf(Number(a.id)),q=l.indexOf(Number(i.id)),H=Ma(l,$,q);S(H),P(H)}const{toast:c}=re(),{weddingQueryParam:I,weddings:G,hasExplicitSelection:le,isMultiWedding:b,setSelectedWeddingId:M}=Ue();wn();const[V,_]=n.useState(!1),[z,De]=n.useState(!1);n.useEffect(()=>{V||y.clearAllFieldErrors()},[V]);const[Ne,Js]=n.useState(!1),[ue,Be]=n.useState(null),[Xs,Ht]=n.useState(!1),[ht,Gt]=n.useState(""),[Zs,Yt]=n.useState(""),[ce,Jt]=n.useState([]),[Xt,Zt]=n.useState(!1),[ie,Qe]=n.useState(null),[ea,es]=n.useState(!1),[ze,ts]=n.useState(""),[gt,We]=n.useState("paste"),[ss,ft]=n.useState(!1),[as,jt]=n.useState(!1),[oe,pe]=n.useState([]),[de,ns]=n.useState(null),{previewRole:ta,isPreviewActive:sa}=sn(),me=sa?ta:u?.role,Y=me==="planner"||me==="photographer"||me==="admin",aa=me==="vendor",na=me==="admin",{canEdit:ra}=xn("vendors"),we=(on(me)||na)&&ra,yt=Y,ia=t=>aa&&t.userId===w?.id,[vt,rs]=n.useState(null),[Z,Te]=n.useState(null),[bt,is]=n.useState(null),[He,ge]=n.useState(""),[oa,Nt]=n.useState(!1),[ne,fe]=n.useState({name:"",category:"",email:""}),[wt,da]=n.useState(!0),[os,ds]=n.useState(!1),ls=n.useRef(null),{data:cs}=B({queryKey:["/api/vendor-info/auto-send"],enabled:Y}),ms=Q({mutationFn:async t=>(await F("PUT","/api/vendor-info/auto-send",{enabled:t})).json(),onSuccess:t=>{A.refetchQueries({queryKey:["/api/vendor-info/auto-send"]}),c({title:t.enabled?"Auto-send enabled":"Auto-send disabled",description:t.enabled?"The vendor info request will automatically be sent to all current and future couples.":"Auto-send has been turned off."})},onError:()=>{c({title:"Couldn’t complete that",description:"Failed to update auto-send setting.",variant:"destructive"})}}),{data:Ct}=B({queryKey:["/api/planner/weddings-list"],enabled:Y}),{data:W}=B({queryKey:["/api/wedding-details"+I]}),{data:Ce}=B({queryKey:["/api/planner-profile"],enabled:Y}
1),ke=me==="photographer"?"Photographer":me==="planner"?"Wedding Planner":null,Se=ke?`vendors:self-credit:${W?.id||"none"}:${ke}`:null,{isDismissed:la,dismiss:ca,restore:ma}=Ga(),us=Se?la(Se):!1,ua=w&&[w.firstName,w.lastName].filter(Boolean).join(" ")||"Your Planner",kt=Y&&ke&&Ce&&!us?{id:-1,category:ke,name:Ce.brandName||ua,instagram:Ce.instagram||null,website:Ce.website||null,isSelf:!0}:null,ps=()=>{Se&&ca(Se)},pa=()=>{Se&&ma(Se)},[xa,je]=n.useState(!1),[xs,hs]=n.useState(!1),[Ae,Ge]=n.useState([]),gs=Oe({type:"vendor_info_request",params:{weddingId:W?.id??0},title:"Vendor Information Request",onSent:()=>{A.refetchQueries({queryKey:["/api/vendor-info/requests"]})}}),fs=Oe({type:"vendor_info_request_bulk",params:{weddingIds:Ae.join(",")},title:"Vendor Information Request (Bulk)",onSent:()=>{Ge([]),A.refetchQueries({queryKey:["/api/vendor-info/requests"]})}}),[nr,rr]=n.useState("now"),[ha,ir]=n.useState("90"),xe=I?I.replace("?weddingId=",""):W?.id?String(W.id):"",[St,js]=n.useState(null),ys=t=>{const a=new Date().toISOString();A.setQueryData(["/api/vendors"+I],i=>
1i&&i.map(l=>l.id===t?{...l,inviteSentAt:a}:l)),A.invalidateQueries({queryKey:["/api/vendors"+I]})},vs=Oe({type:"vendor_invite",params:{vendorId:Z?.id??0,message:He},title:"Vendor invite",onSent:()=>{Z&&ys(Z.id),Te(null),ge("")}}),bs=Oe({type:"vendor_invite",params:{vendorId:St??0,message:He},title:"Vendor invite",onSent:()=>{St&&ys(St),js(null)}}),Ns=Oe({type:"vendor_invite_all",params:{weddingId:xe},title:"Invite all vendors",onSent:()=>{const t=new Date().toISOString();A.setQueryData(["/api/vendors"+I],a=>a&&a.map(i=>i.email&&!i.inviteSentAt?{...i,inviteSentAt:t}:i)),A.invalidateQueries({queryKey:["/api/vendors"+I]})}}),{data:ga=[]}=B({queryKey:["/api/vendor-info/schedules",xe],queryFn:async()=>xe?(await F("GET",`/api/vendor-info/schedules?weddingId=${xe}`)).json():[],enabled:Y&&!!xe});Q({mutationFn:async({weddingId:t,daysBefore:a})=>(await F("POST","/api/vendor-info/schedule",{weddingId:t,daysBefore:a})).json(),onSuccess:()=>{A.refetchQueries({queryKey:["/api/vendor-info/schedules"]}),je(!1),c({title:"Scheduled",description:`Vendor info request will be sent ${ha} days before the wedding.`})},onError:()=>{c({title:"Couldn’t complete that",description:"Failed to schedule request.",variant:"destructive"})}}),Q({mutationFn:async({weddingIds:t,daysBefore:a})=>(await F("POST","/api/vendor-info/schedule-bulk",{weddingIds:t,daysBefore:a})).json(),onSuccess:t=>{A.refetchQueries({queryKey:["/api/vendor-info/schedules"]}),je(!1),Ge([]),c({title:"Scheduled",description:`Successfully scheduled for ${t.successCount} of ${t.totalCount} wedding${t.totalCount!==1?"s":""}.`})},onError:()=>{c({title:"Couldn’t complete that",description:"Failed to schedule bulk requests.",variant:"destructive"})}}),Q({mutationFn:async t=>{await F("DELETE",`/api/vendor-info/schedules/${t}`)},onSuccess:()=>{A.refetchQueries({queryKey:["/api/vendor-info/schedules"]}),c({title:"Schedule removed"})}}),ga.filter(t=>!t.sent);const Pt=Q({mutationFn:async t=>(await F("POST",`/api/vendors/invite${I}`,{...t,name:$e(t.name),deferEmail:!0})).json(),onSuccess:t=>{Nt(!1),fe({name:"",category:"",email:""}),It(null),t?.vendor?.id&&(js(t.vendor.id),ge(""),bs.openPreview()),t?.vendor&&A.setQueryData(["/api/vendors"+I],a=>a?[...a,t.vendor]:[t.vendor]),A.invalidateQueries({queryKey:["/api/vendors"+I]})},onError:t=>{c({title:"Couldn’t complete that",description:t.message,variant:"destructive"})}}),[$t,It]=n.useState(null),fa=t=>{fe({...ne,name:t}),Pe.current&&clearTimeout(Pe.current),Pe.current=setTimeout(()=>ks(t),300)},ja=t=>{fe({name:t.name||"",category:t.category||"",email:t.email||""}),It({name:t.name||"",category:t.category||"",pointOfContact:t.pointOfContact||"",email:t.email||"",instagram:t.instagram||"",website:t.website||"",description:t.description||"",phone:t.phone||""}),he(!1),ve([])},ya=()=>{const t=$t&&$t.name===ne.name?$t:ne;Pt.mutate(t)},[j,R]=n.useState(_e),[ye,ve]=n.useState([]),[Vt,Et]=n.useState([]),[ws,he]=n.useState(!1),Ye=n.useRef(null),Pe=n.useRef(null),[Cs,Je]=n.useState(!1),{data:Ft=[]}=B({queryKey:["/api/preferred-vendors"],enabled:Y}),ks=n.useCallback(async t=>{if(t.length<2){ve([]),Et([]);return}try{const a=await F("GET",`/api/vendors/search?q=${encodeURIComponent(t)}`);if(a.ok){const i=await a.json();ve(i)}}catch{ve([])}if(Y&&Ft.length>0){const a=t.toLowerCase(),i=Ft.filter(l=>l.name?.toLowerCase().includes(a)||l.company?.toLowerCase().includes(a)||l.category?.toLowerCase().includes(a));Et(i.slice(0,5))}},[Y,Ft]),va=t=>{R({...j,name:t}),Je(!1),Pe.current&&clearTimeout(Pe.current),Pe.current=setTimeout(()=>{ks(t),he(!0)},300)},ba=ye.length>0||Vt.length>0,Na=t=>{R(a=>({...a,name:t.name||"",category:t.category||"",pointOfContact:t.pointOfContact||"",email:t.email||"",instagram:t.instagram||"",website:t.website||"",description:t.description||"",phone:t.phone||""})),he(!1),ve([])};n.useEffect(()=>{const t=a=>{Ye.current&&!Ye.current.contains(a.target)&&he(!1)};return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[]);const wa=()=>{Be(null),R(_e),ve([]),he(!1),_(!0)},Ca=t=>{Be(t),R({name:t.name||"",category:t.category||"",pointOfContact:t.pointOfContact||"",email:t.email||"",instagram:t.instagram||"",website:t.website||"",description:t.description||"",phone:t.phone||"",totalCost:t.totalCost?String(t.totalCost/100):"",depositAmount:t.depositAmount?String(t.depositAmount/100):"",amountPaid:t.amountPaid?String(t.amountPaid/100):"",paymentStatus:t.paymentStatus||"unpaid",contractUrl:t.contractUrl||"",paymentDueDate:t.paymentDueDate||"",paymentNotes:t.paymentNotes||""}),_(!0)},Ss=()=>{const{totalCost:t,depositAmount:a,amountPaid:i,instagram:l,...$}=j;return{...$,name:$e($.name),instagram:Lt(l),totalCost:t?Math.round(parseFloat(t)*100):null,depositAmount:a?Math.round(parseFloat(a)*100):null,amountPaid:i?Math.round(parseFloat(i)*100):null}},ka=()=>{y.clearAllFieldErrors(),ue?v({id:ue.id,...Ss()},{onSuccess:()=>{_(!1),Be(null),R(_e)}}):!le&&b?De(!0):Ps()},Ps=t=>{const a=$e(j.name),i=j.email,l=wt&&!!i,$=Cs,q={...j,name:a};k({...Ss(),status:"approved",targetWeddingId:t},{onSuccess:H=>{_(!1),R(_e),Je(!1),i||c({title:"Vendor added",description:"Add an email to give this vendor a collaborator portal. Their login uses their email."}),l&&H?.id&&(Te(H),ge(""),c({title:"Vendor added",description:`Review the invite to ${a} and send it when it reads right.`})),$&&F("POST","/api/preferred-vendors",{name:q.name,category:q.category,email:q.email||void 0,phone:q.phone||void 0,website:q.website||void 0,instagram:q.instagram||void 0}).then(()=>{c({title:"Saved to your Vendor Directory",description:`${a} added to your vendor rolodex.`}
1),A.invalidateQueries({queryKey:["/api/preferred-vendors"]})}).catch(()=>{})}})},Sa=()=>{if(!d?.length)return;const t=d.filter(a=>a.email).map(a=>a.email).join(", ");if(!t){c({title:"No Emails",description:"No vendor emails to copy."});return}navigator.clipboard.writeText(t),c({title:"Copied",description:"All vendor emails copied to clipboard."})},$s=["Wedding Planner","Ceremony Venue","Ceremony Location","Reception Venue","Reception Location","Photographer","Second Photographer","Videographer","Florist"],Pa=t=>{const a=i=>{const l=(i??"").toLowerCase(),$=$s.findIndex(q=>q.toLowerCase()===l);return $===-1?$s.length:$};return[...t].sort((i,l)=>{const $=a(i.category),q=a(l.category);if($!==q)return $-q;const H=(i.category??"").toLowerCase(),be=(l.category??"").toLowerCase();return H!==be?(i.category??"").localeCompare(l.category??""):(i.name??"").localeCompare(l.name??"")})},Xe=()=>{const t=[W?.partner1Instagram,W?.partner2Instagram].map(a=>a?String(a).trim():"").filter(Boolean);return t.length===0?null:`The couple: ${t.join(" & ")}`},Ze=t=>{const a=[...t];return kt&&(t.some(l=>(l.category??"").toLowerCase()===(kt.category??"").toLowerCase())||a.push(kt)),Cn(Pa(a))},qe=t=>{const a=t??"";return a.charAt(0).toUpperCase()+a.slice(1)},$a=()=>{const t=Ze(d||[]);if(!t.length)return;const a=[],i=Xe();i&&a.push(i),t.forEach(l=>{const $=l.instagram?l.instagram.trim().replace(/^@/,"").trim():null,q=$?`@${$}`:Me(l);a.push(`${qe((l.category??"").trim())}: ${q}`)}),navigator.clipboard.writeText(a.join(`
2`)),c({title:"Copied",description:"Vendor credits copied to clipboard."})},Ia=()=>{const t=Ze(d||[]);if(!t.length)return;const a=[],i=Xe();i&&a.push(i),t.forEach(l=>{const $=l.website?l.website.trim():null,q=$?$.startsWith("http")?$:`https://${$}`:null;q?a.push(`${qe((l.category??"").trim())}: <a href="${q}" target="_blank" rel="noopener noreferrer">${Me(l)}</a>`):a.push(`${qe((l.category??"").trim())}: ${Me(l)}`)}),navigator.clipboard.writeText(a.join(`
3`)),c({title:"Copied",description:"Vendor list with website links copied, ready to paste into your website."})},Va=t=>{const a=t.target.files?.[0];if(!a)return;Yt(a.name),Qe(null);const i=new FileReader;i.onload=l=>{const $=l.target?.result;Gt($);const H=$.split(`
4`).filter(be=>be.trim()).slice(0,6).map(be=>{const Dt=[];let et="",Tt=!1;for(const At of be){if(At==='"'){Tt=!Tt;continue}if(At===","&&!Tt){Dt.push(et.trim()),et="";continue}et+=At}return Dt.push(et.trim()),Dt});Jt(H)},i.readAsText(a)},Ea=async()=>{if(ht){Zt(!0),Qe(null);try{const a=await(await F("POST","/api/vendors/import-csv"+I,{csvContent:ht})).json();Qe(a),a.imported>0&&(A.refetchQueries({queryKey:["/api/vendors"+I]}),c({title:"Import Complete",description:`${a.imported} vendor${a.imported!==1?"s":""} imported successfully.${a.errors>0?` ${a.errors} row${a.errors!==1?"s":""} had errors.`:""}`}))}catch(t){const a=await Fs(t).json?.().catch(()=>null);c({title:"Import Failed",description:a?.message||"Could not import the CSV file. Please check the format.",variant:"destructive"})}finally{Zt(!1)}}},Is=()=>{Gt(""),Yt(""),Jt([]),Qe(null),Ht(!1)},Vs=()=>{ts(""),We("paste"),pe([]),ns(null),ft(!1),jt(!1),es(!1)},Fa=async()=>{if(ze.trim()){ft(!0);try{const a=await(await F("POST","/api/vendors/parse-text"+I,{text:ze})).json();pe(a.vendors.map(i=>({...i,instagram:i.existingVendor?.instagram||i.instagram||"",website:i.existingVendor?.website||"",email:i.existingVendor?.email||"",phone:i.existingVendor?.phone||"",pointOfContact:i.existingVendor?.pointOfContact||"",skip:!1}))),We("review")}catch(t){const a=await Fs(t).json?.().catch(()=>null);c({title:"Couldn't parse that",description:a?.message||"Could not parse the vendor list. Try a different format.",variant:"destructive"})}finally{ft(!1)}}},Da=async()=>{const t=oe.filter(a=>!a.skip);if(t.length!==0){jt(!0);try{const a=t.map($=>({name:$.name,category:$.category,existingId:$.existingVendor?.id||null,instagram:$.instagram||null,website:$.website||null,email:$.email||null,phone:$.phone||null,pointOfContact:$.pointOfContact||null})),l=await(await F("POST","/api/vendors/bulk-import"+I,{vendors:a})).json();ns(l),We("done"),(l.created>0||l.updated>0)&&A.refetchQueries({queryKey:["/api/vendors"+I]})}catch{c({title:"Import Failed",description:"Could not import vendors. Please try again.",variant:"destructive"})}finally{jt(!1)}}};return e.jsxs("div",{className:"max-w-7xl mx-auto px-6 sm:px-8 lg:px-10 py-8",children:[e.jsx(hn,{pageKey:"vendors"}),e.jsx(jn,{title:"What is this?",description:"Your Vendor Manager tracks every vend
4or you're considering or have booked — photographers, caterers, florists, DJs, and more. Compare quotes, store contracts, and keep all their details in one place.",guideSlug:"vendors",storageKey:"vendors",steps:["Click 'Add Vendor' to save a vendor with their category, pricing, and contact info.","Track their booking status — researching, contacted, booked, or paid.","Store contracts, notes, and payment records for each vendor."]}),e.jsxs("div",{className:"flex flex-wrap justify-between items-start gap-4 mb-8",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] tracking-[0.3em] uppercase text-muted-foreground/70 mb-3",children:"Vendors"}),e.jsxs("h1",{className:"font-display text-3xl font-light tracking-tight text-foreground mb-2 flex items-center gap-2","data-testid":"text-vendor-title",children:["Vendor Directory"," ",e.jsx(Ba,{text:"Keep all your vendor contacts, contracts, and payment details organized.",pageId:"vendors"})]}),e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Your dream team, all in one place."})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[we&&d&&d.length>0&&xe&&e.jsx(Sn,{contentType:"vendors",fromWeddingId:Number(xe)}),d&&d.length>0&&e.jsx(e.Fragment,{children:yt&&e.jsxs(C,{variant:"outline",className:"tracking-wider uppercase text-xs",onClick:Ns.openPreview,disabled:!xe||!d.some(t=>t.email&&!t.inviteSentAt),"data-testid":"button-invite-all",children:[e.jsx(Us,{className:"w-4 h-4 mr-2"}),"Invite All"]})}),we&&e.jsxs(e.Fragment,{children:[Y&&e.jsxs(e.Fragment,{children:[e.jsx(Un,{weddingId:W?.id,vendorsQueryKey:"/api/vendors"+I,existingNames:(d||[]).map(t=>t.name||"")}),e.jsx(Kn,{weddingId:W?.id,vendorsQueryKey:"/api/vendors"+I})]}),e.jsxs(ee,{open:Xs,onOpenChange:t=>{t?Ht(!0):Is()},children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(C,{variant:"outline",className:"tracking-wider uppercase text-xs","data-testid":"button-import-csv",children:[e.jsx(Ts,{className:"w-4 h-4 mr-2"}),"Import CSV"]})}),e.jsxs(te,{className:"max-w-lg max-h-[90vh] overflow-y-auto",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:"Import Vendors from CSV"})}),e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Upload a CSV file with your vendor list. The system will automatically detect columns like Name, Category, Email, Phone, Instagram, Website, Point of Contact, and Description. Include the country code on international numbers, like +39 06 1234 5678."}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(T,{children:"Choose CSV File"}),e.jsx(O,{type:"file",accept:".csv,text/csv",onChange:Va,"data-testid":"input-csv-file"})]}),ce.length>0&&!ie&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(In,{className:"w-4 h-4 text-muted-foreground"}),e.jsx("span",{className:"text-sm font-medium",children:Zs}),e.jsx(J,{variant:"secondary",children:ce.length>1?`${ce.length-1} rows`:"0 rows"})]}),e.jsx("div",{className:"overflow-x-auto border rounded-md",children:e.jsxs("table",{className:"w-full text-xs","data-testid":"table-csv-preview",children:[e.jsx("thead",{children:e.jsx("tr",{className:"border-b bg-muted/50",children:ce[0]?.map((t,a)=>e.jsx("th",{className:"px-3 py-2 text-left font-medium",children:t},a))})}),e.jsx("tbody",{children:ce.slice(1,6).map((t,a)=>e.jsx("tr",{className:"border-b last:border-0",children:t.map((i,l)=>e.jsx("td",{className:"px-3 py-2 max-w-[150px] truncate",children:i},l))},a))})]})}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Showing preview of first ",Math.min(ce.length-1,5)," row",ce.length-1!==1?"s":"",'. Any category not matching an existing type will be imported as "Other".']}),e.jsx(U,{className:"w-full tracking-wider uppercase",onClick:Ea,disabled:Xt,"data-testid":"button-csv-import-confirm",children:Xt?"Importing...":`Import ${ce.length-1} Vendor${ce.length-1!==1?"s":""}`})]}),ie&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(As,{className:"w-5 h-5 text-green-600"}),e.jsxs("span",{className:"font-medium",children:[ie.imported," vendor",ie.imported!==1?"s":""," imported successfully"]})]}),ie.mappedColumns.length>0&&e.jsxs("div",{className:"text-xs text-muted-foreground",children:[e.jsx("span",{className:"font-medium",children:"Columns matched:"}
4)," ",ie.mappedColumns.join(", ")]}),ie.errors>0&&e.jsxs("div",{className:"space-y-1",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-destructive",children:[e.jsx(an,{className:"w-4 h-4"}),e.jsxs("span",{children:[ie.errors," row",ie.errors!==1?"s":""," had errors"]})]}),e.jsx("div",{className:"text-xs text-muted-foreground space-y-0.5",children:ie.errorDetails.map((t,a)=>e.jsxs("div",{children:["Row ",t.row,": ",t.error]},a))})]}),e.jsx(C,{variant:"outline",className:"w-full tracking-wider uppercase text-xs",onClick:Is,"data-testid":"button-csv-done",children:"Done"})]}),!ht&&e.jsxs("div",{className:"bg-muted/30 rounded-md p-4 space-y-2",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground tracking-wider uppercase",children:"Expected CSV Format"}),e.jsxs("pre",{className:"text-xs text-muted-foreground whitespace-pre-wrap font-mono leading-relaxed",children:["Name,Category,Email,Phone,Instagram,Website,Point of Contact,Description",`
5`,"Dreamy Photography,Photographer,[email protected],+1 555 010 2030,@dreamyphoto,dreamy.com,Sarah J,Full day coverage",`
6`,"Rose Garden Florals,Florist,[email protected],+39 06 1234 5678, @rosegardenfl,,Maria R,Bouquets and centerpieces"]})]})]})]})]}),e.jsxs(ee,{open:ea,onOpenChange:t=>{t?es(!0):Vs()},children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(C,{variant:"outline",className:"tracking-wider uppercase text-xs","data-testid":"button-paste-vendor-list",children:[e.jsx(ct,{className:"w-4 h-4 mr-2"}),"Paste Vendor List"]})}),e.jsxs(te,{className:"max-w-2xl max-h-[90vh] overflow-y-auto",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:"Import from Vendor List"})}),gt==="paste"&&e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Paste a vendor list from a planner, venue, or coordinator. Any format works — the system will parse it automatically."}),e.jsx(rt,{placeholder:`Wedding Planning and Design | Evergreen Events Co.
7Florals and Design | Wildflower Studio
8Photography | Northlight Photography
9Videography | Blue Hour Films
10...`,value:ze,onChange:t=>ts(t.target.value),rows:10,className:"font-mono text-sm","data-testid":"textarea-paste-vendors"}),e.jsx(U,{className:"w-full tracking-wider uppercase",onClick:Fa,disabled:!ze.trim()||ss,"data-testid":"button-parse-vendors",children:ss?e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"})," Parsing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Gs,{className:"w-4 h-4 mr-2"})," Parse Vendor List"]})})]}),gt==="review"&&e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Review the parsed vendors below. Vendors already in your system are highlighted — you can add missing details to update them. Uncheck any you don't want to import."}),e.jsx("div",{className:"space-y-3",children:oe.map((t,a)=>e.jsx("div",{className:`border rounded-lg p-3 transition-colors ${t.skip?"opacity-40":""} ${t.matched?"border-green-300 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20":""}`,"data-testid":`paste-vendor-row-${a}`,children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(mt,{checked:!t.skip,onCheckedChange:i=>{const l=[...oe];l[a]={...l[a],skip:!i},pe(l)},className:"mt-1","data-testid":`checkbox-vendor-${a}`}),e.jsxs("div",{className:"flex-1 space-y-2 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-sm font-medium",children:t.name}),e.jsx(J,{variant:"secondary",className:"text-[11px]",children:t.category}),t.matched&&e.jsxs(J,{variant:"outline",className:"text-[11px] border-green-400 text-green-700 dark:text-green-400",children:[e.jsx(ut,{className:"w-3 h-3 mr-0.5"})," Already exists"]})]}),!t.skip&&e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{className:"text-[11px] text-muted-foreground",children:"Instagram"}),e.jsx(O,{value:t.instagram,onChange:i=>{const l=[...oe];l[a]={...l[a],instagram:i.target.value},pe(l)},placeholder:"@handle",className:"h-7 text-xs","data-testid":`input-vendor-instagram-${a}`})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{className:"text-[11px] text-muted-foreground",children:"Website"}),e.jsx(O,{value:t.website,onChange:i=>{const l=[...oe];l[a]={...l[a],website:i.target.value},pe(l)},placeholder:"vendor.com",className:"h-7 text-xs","data-testid":`input-vendor-website-${a}`})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{className:"text-[11px] text-muted-foreground",children:"Email"}),e.jsx(O,{value:t.email,onChange:i=>{const l=[...oe];l[a]={...l[a],email:i.target.value},pe(l)},placeholder:"[email protected]",className:"h-7 text-xs","data-testid":`input-vendor-email-${a}`})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{className:"text-[11px] text-muted-foreground",children:"Phone"}),e.jsx(O,{value:t.phone,onChange:i=>{const l=[...oe];l[a]={...l[a],phone:i.target.value},pe(l)},placeholder:"(555) 123-4567",className:"h-7 text-xs","data-testid":`input-vendor-phone-${a}`})]})]})]})]})},a))}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(C,{variant:"outline",className:"flex-1 tracking-wider up
10percase text-xs",onClick:()=>{We("paste"),pe([])},"data-testid":"button-paste-back",children:"Back"}),e.jsx(C,{variant:"outline",className:"flex-1 tracking-wider uppercase",onClick:Da,disabled:as||oe.every(t=>t.skip),"data-testid":"button-bulk-import",children:as?e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"})," Importing..."]}):`Import ${oe.filter(t=>!t.skip).length} Vendor${oe.filter(t=>!t.skip).length!==1?"s":""}`})]})]}),gt==="done"&&de&&e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(As,{className:"w-5 h-5 text-green-600"}),e.jsx("span",{className:"font-medium",children:"Import complete"})]}),e.jsxs("div",{className:"space-y-1 text-sm text-muted-foreground",children:[de.created>0&&e.jsxs("p",{children:[de.created," new vendor",de.created!==1?"s":""," added"]}),de.updated>0&&e.jsxs("p",{children:[de.updated," existing vendor",de.updated!==1?"s":""," ","updated"]}),de.errors>0&&e.jsxs("p",{className:"text-destructive",children:[de.errors," error",de.errors!==1?"s":""]})]}),e.jsx(C,{variant:"outline",className:"w-full tracking-wider uppercase text-xs",onClick:Vs,"data-testid":"button-paste-done",children:"Done"})]})]})]}),e.jsxs(ee,{open:oa,onOpenChange:t=>{Nt(t),t||(fe({name:"",category:"",email:""}),It(null))},children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(C,{variant:"outline",className:"tracking-wider uppercase text-xs","data-testid":"button-quick-invite-vendor",children:[e.jsx(Ve,{className:"w-4 h-4 mr-2"}),"Invite Vendor"]})}),e.jsxs(te,{className:"max-w-md",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:"Invite a Vendor"})}),e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed",children:"Send an email invitation to a vendor. They'll receive a link to complete their profile with contact info, social media, and how they'd like to be credited."}),e.jsxs("div",{className:"grid gap-4 py-2",children:[e.jsxs("div",{className:"grid gap-2 relative",children:[e.jsx(T,{children:"Business Name"}),e.jsx(O,{value:ne.name,onChange:t=>fa(t.target.value),onBlur:()=>fe(t=>({...t,name:$e(t.name)})),autoCapitalize:"words",onFocus:()=>{ye.length>0&&he(!0)},placeholder:"e.g. Dreamy Photography","data-testid":"input-quick-invite-name"}),ws&&ye.length>0&&e.jsx("div",{ref:Ye,className:"absolute z-50 top-full left-0 right-0 mt-1 bg-popover border border-border rounded-md shadow-md max-h-48 overflow-y-auto","data-testid":"quick-add-vendor-suggestions-dialog",children:ye.map((t,a)=>e.jsxs("button",{type:"button",className:"w-full text-left px-3 py-2 text-sm hover:bg-accent transition-colors flex flex-col",onClick:()=>ja(t),children:[e.jsxs("span",{className:"font-medium",children:[t.name,t.source==="network"&&e.jsx("span",{className:"ml-2 text-[10px] uppercase tracking-wide text-muted-foreground",children:"On Colara"})]}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:[t.category," • ",t.pointOfContact||"No contact"]})]},a))})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Category"}),e.jsxs(tt,{value:ne.category,onValueChange:t=>fe({...ne,category:t}),children:[e.jsx(st,{"data-testid":"select-quick-invite-category",children:e.jsx(at,{placeholder:"What do they do?"})}),e.jsx(nt,{children:e.jsx(_t,{})})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Email Address"}),e.jsx(O,{type:"email",value:ne.email,onChange:t=>fe({...ne,email:t.target.value}),placeholder:"[email protected]","data-testid":"input-quick-invite-email"})]})]}),e.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[e.jsx(C,{variant:"outline",onClick:()=>Nt(!1),"data-testid":"button-cancel-quick-invite",children:"Cancel"}),e.jsx(U,{onClick:ya,disabled:!ne.name||!ne.category||!ne.email||Pt.isPending,"data-testid":"button-send-quick-invite",children:Pt.isPending?e.jsxs(e.Fragment,{children:[e.jsx(X,{className:"w-4 h-4 mr-2 animate-spin"})," Sending..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Ve,{className:"w-4 h-4 mr-2"})," Send Invite"]})})]})]})]}),W?.id?e.jsx(Pn,{weddingId:W.id,coupleNames:W.coupleNames,label:"Add Co-Planner",className:"tracking-wider up
10percase",testId:"button-add-coplanner-vendors"}):null,e.jsxs(ee,{open:V,onOpenChange:t=>{_(t),t||Be(null)},children:[e.jsx(Ie,{asChild:!0,children:e.jsxs(U,{className:"tracking-wider uppercase",onClick:wa,"data-testid":"button-add-vendor",children:[e.jsx(Kt,{className:"w-4 h-4 mr-2"}),"Add Vendor"]})}),e.jsxs(te,{className:"max-w-md max-h-[90vh] overflow-y-auto",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:ue?"Edit Vendor":"Add New Vendor"})}),!ue&&Y&&e.jsx(mn,{onSelect:t=>{R(a=>({...a,name:t.name||"",category:t.category||"",pointOfContact:t.name||"",email:t.email||"",instagram:t.instagram||"",website:t.website||"",description:"",phone:t.phone||""}))}}),e.jsxs("div",{className:"grid gap-4 py-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Business Name"}),e.jsxs("div",{className:"relative",ref:Ye,children:[e.jsx(O,{value:j.name,onChange:t=>{va(t.target.value),y.clearFieldError("name")},onFocus:()=>{ye.length>0&&he(!0)},placeholder:"e.g. Dreamy Photography",autoComplete:"off",autoCapitalize:"words",onBlur:()=>R(t=>({...t,name:$e(t.name)})),"data-testid":"input-vendor-name","aria-invalid":!!y.fieldErrors.name}),e.jsx(Rt,{message:y.fieldErrors.name,testId:"error-vendor-name"}),ws&&ba&&!ue&&e.jsxs("div",{className:"absolute z-50 top-full left-0 right-0 mt-1 bg-popover border border-border rounded-md shadow-md max-h-56 overflow-y-auto","data-testid":"vendor-suggestions",children:[Vt.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"text-[10px] tracking-wider uppercase text-muted-foreground px-3 pt-2 pb-1 flex items-center gap-1.5",children:[e.jsx(lt,{className:"w-3 h-3"})," Your Vendor Directory"]}),Vt.map(t=>e.jsxs("button",{type:"button",className:"w-full text-left px-3 py-2 hover:bg-accent transition-colors flex items-center gap-2",onClick:()=>{R(a=>({...a,name:t.name||"",category:t.category||"",pointOfContact:t.name||"",email:t.email||"",instagram:t.instagram||"",website:t.website||"",description:"",phone:t.phone||""})),he(!1),Et([]),ve([])},"data-testid":`suggestion-preferred-${t.id}`,children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:t.name}),e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:[t.category,t.company?` · ${t.company}`:"",t.email?` · ${t.email}`:""]})]}),e.jsx(J,{variant:"outline",className:"text-[9px] shrink-0",children:"Preferred"})]},`pv-${t.id}`))]}),ye.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-[10px] tracking-wider uppercase text-muted-foreground px-3 pt-2 pb-1",children:"Other matches"}),ye.map((t,a)=>e.jsxs("button",{type:"button",className:"w-full text-left px-3 py-2 hover:bg-accent transition-colors flex items-center gap-2",onClick:()=>Na(t),"data-testid":`suggestion-vendor-${a}`,children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:t.name}),e.jsxs("p",{className:"text-xs text-muted-foreground truncate",children:[t.category,t.email?` · ${t.email}`:""]})]}),t.source==="network"&&e.jsx(J,{variant:"outline",className:"shrink-0 text-[10px]",children:"On Colara"})]},a))]})]})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Category"}),(()=>{const t=!!j.category&&!un.includes(j.category),a=t?"__custom__":j.category;return e.jsxs(e.Fragment,{children:[e.jsxs(tt,{value:a,onValueChange:i=>{y.clearFieldError("category"),R(i==="__custom__"?{...j,category:" "}:{...j,category:i})},children:[e.jsx(st,{"data-testid":"select-vendor-category","aria-invalid":!!y.fieldErrors.category,children:e.jsx(at,{placeholder:"What do they do?"})}),e.jsxs(nt,{children:[e.jsx(_t,{}),e.jsx(Re,{value:"__custom__",children:"+ Add custom category…"})]})]}),t&&e.jsx(O,{autoFocus:!0,value:j.category.trim()===""?"":j.category,onChange:i=>{R({...j,category:i.target.value||" "}),y.clearFieldError("category")},placeholder:"Type your custom category","data-testid":"input-vendor-category-custom"}),e.jsx(Rt,{message:y.fieldErrors.category,testId:"error-vendor-category"})]})})()]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Point of Contact"}),e.jsx(O,{value:j.pointOfContact,onChange:t=>R({...j,pointOfContact:t.target.value}),placeholder:"e.g. Sarah Johnson","data-testid":"input-vendor-poc"})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Email Address"}),e.jsx(O,{type:"email",value:j.email,onChange:t=>{R({...j,email:t.target.value}),y.clearFieldError("email")},placeholder:"[email protected]","data-testid":"input-vendor-email","aria-invalid":!!y.fieldErrors.email}),e.jsx(Rt,{message:y.fieldErrors.email,testId:"error-vendor-email"})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Phone Number"}),e.jsx(O,{type:"tel",value:j.phone,onChange:t=>R({...j,phone:t.target.value}),placeholder:"(555) 123-4567","data-testid":"input-vendor-phone"})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Instagram Handle"}),e.jsx(O,{value:j.instagram,onChange:t=>R({...j,instagram:t.target.value}),placeholder:"@vendorhandle","data-testid":"input-vendor-instagram"})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Website"}),e.jsx(O,{value:j.website,onChange:t=>R({...j,website:t.target.value}),placeholder:"www.vendor.com","data-testid":"input-vendor-website"})]}),e.jsxs("div",{className:"border-t pt-4 mt-2",children:[e.jsxs("button",{type:"button",onClick:()=>Js(t=>
10!t),className:"flex items-center gap-1.5 text-[11px] tracking-[0.2em] uppercase text-muted-foreground/70 hover:text-foreground transition-colors mb-3","data-testid":"button-toggle-financials",children:[Ne?e.jsx(nn,{className:"w-3 h-3"}):e.jsx(Vn,{className:"w-3 h-3"}),"Financials",!Ne&&e.jsx("span",{className:"text-[10px] tracking-normal normal-case text-muted-foreground ml-1",children:"(optional)"})]}),Ne&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Total Cost"}),e.jsxs("div",{className:"relative",children:[e.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm",children:m}),e.jsx(O,{type:"number",step:"0.01",min:"0",value:j.totalCost,onChange:t=>R({...j,totalCost:t.target.value}),placeholder:"0.00",className:N,"data-testid":"input-vendor-total-cost"})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Deposit"}),e.jsxs("div",{className:"relative",children:[e.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm",children:m}),e.jsx(O,{type:"number",step:"0.01",min:"0",value:j.depositAmount,onChange:t=>R({...j,depositAmount:t.target.value}),placeholder:"0.00",className:N,"data-testid":"input-vendor-deposit"})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Amount Paid"}),e.jsxs("div",{className:"relative",children:[e.jsx("span",{className:"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm",children:m}),e.jsx(O,{type:"number",step:"0.01",min:"0",value:j.amountPaid,onChange:t=>R({...j,amountPaid:t.target.value}),placeholder:"0.00",className:N,"data-testid":"input-vendor-amount-paid"})]})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(T,{children:"Payment Status"}),e.jsxs(tt,{value:j.paymentStatus,onValueChange:t=>R({...j,paymentStatus:t}),children:[e.jsx(st,{"data-testid":"select-vendor-payment-status",children:e.jsx(at,{})}),e.jsxs(nt,{children:[e.jsx(Re,{value:"unpaid",children:"Unpaid"}),e.jsx(Re,{value:"deposit",children:"Deposit Paid"}),e.jsx(Re,{value:"partial",children:"Partially Paid"}),e.jsx(Re,{value:"paid",children:"Paid in Full"})]})]})]})]}),e.jsxs("div",{className:"grid gap-2 mt-3",children:[e.jsx(T,{children:"Payment Due Date"}),e.jsx(O,{type:"date",value:j.paymentDueDate,onChange:t=>R({...j,paymentDueDate:t.target.value}),"data-testid":"input-vendor-payment-due"})]}),e.jsxs("div",{className:"grid gap-2 mt-3",children:[e.jsx(T,{children:"Contract"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(O,{value:j.contractUrl,onChange:t=>R({...j,contractUrl:t.target.value}),placeholder:"https://... or upload a file","data-testid":"input-vendor-contract-url",className:"flex-1"}),e.jsx(C,{type:"button",variant:"outline",disabled:os,onClick:()=>ls.current?.click(),"data-testid":"button-upload-contract",children:os?e.jsx(X,{className:"h-4 w-4 animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx(Ts,{className:"h-4 w-4 mr-1"}),"Upload"]})}),e.jsx("input",{ref:ls,type:"file",accept:".pdf,.doc,.docx,.txt,.png,.jpg,.jpeg,application/pdf",className:"hidden",onChange:async t=>{const a=t.target.files?.[0];if(a){if(a.size>25*1024*1024){c({title:"File too large",description:"Maximum 25MB.",variant:"destructive"}),t.target.value="";return}try{ds(!0);const i=await F("POST","/api/uploads/request-url",{name:a.name,size:a.size,contentType:a.type||"application/octet-stream"}),{uploadURL:l,objectPath:$}=await i.json();if(!(await fetch(l,{method:"PUT",headers:{"Content-Type":a.type||"application/octet-stream"},body:a})).ok)throw new Error("Upload failed");R(H=>({...H,contractUrl:$})),c({title:"Contract uploaded",description:a.name})}catch(i){c({title:"Upload failed",description:i instanceof Error?i.message:"Please try again.",variant:"destructive"})}finally{ds(!1),t.target.value=""}}}})]}),j.contractUrl&&j.contractUrl.startsWith("/objects/")&&e.jsxs("p",{className:"text-xs text-muted-foreground flex items-center gap-1",children:[e.jsx(ct,{className:"h-3 w-3"}),"File uploaded"]})]}),e.jsxs("div",{className:"grid gap-2 mt-3",children:[e.jsx(T,{children:"Payment Notes"}),e.jsx(rt,{value:j.paymentNotes,onChange:t=>R({...j,paymentNotes:t.target.value}),placeholder:"Payment schedule, terms, etc.",rows:2,className:"resize-none","data-testid":"input-vendor-payment-notes"})]})]})]}),!ue&&j.email&&yt&&e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer select-none","data-testid":"label-auto-invite",children:[e.jsx("input",{type:"checkbox",checked:wt,onChange:t=>da(t.target.checked),className:"rounded border-border accent-primary w-4 h-4","data-testid":"checkbox-auto-invite"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:"Invite them to Colara (you review the email first)"})]}),!ue&&Y&&j.name&&e.jsxs("label",{className:"flex items-center gap-2 cursor-pointer select-none","data-testid":"label-save-to-preferred",children:[e.jsx("input",{type:"checkbox",checked:Cs,onChange:t=>Je(t.target.checked),className:"rounded border-border accent-primary w-4 h-4","data-testid":"checkbox-save-to-preferred"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:"Also save to my Vendor Directory"})]}),e.jsx(U,{onClick:ka,disabled:r||E||!j.name||!j.category,className:"tracking-wider up
10percase","data-testid":"button-submit-vendor",children:r||E?"Saving...":ue?"Save Changes":wt&&j.email?"Add & Invite":"Add Vendor"})]})]})]}),e.jsx(Jn,{open:z,onOpenChange:De,weddings:G,vendorName:j.name,preferredPayload:{name:j.name,category:j.category,email:j.email||void 0,phone:j.phone||void 0,website:j.website||void 0,instagram:Lt(j.instagram)||void 0},onPickWedding:t=>{M(t),Ps(t)},onSavedPreferredOnly:()=>{_(!1),R(_e),Je(!1)}})]})]})]}),we&&e.jsx(Wn,{weddingQueryParam:I}),d&&d.length>0&&e.jsxs(Ee,{className:"mb-8",children:[e.jsx(dt,{className:"pb-3",children:e.jsx(Mt,{className:"font-display text-lg font-normal",children:"Vendor Credits"})}),e.jsxs(Fe,{children:[e.jsx(Qn,{currentWedding:W}),Y&&ke&&us&&e.jsxs("div",{className:"mb-4 flex items-center justify-between gap-2 flex-wrap p-3 rounded-md border border-dashed",children:[e.jsxs("div",{className:"text-sm text-muted-foreground",children:["Your card (",ke,") is hidden from this credits list."]}),e.jsx(C,{variant:"outline",size:"sm",className:"tracking-wider uppercase text-xs",onClick:pa,"data-testid":"button-restore-self-credit",children:"Add Me Back"})]}),e.jsx("p",{className:"text-sm text-muted-foreground mb-3",children:"Ready to share on social media or with your guests:"}),e.jsxs("div",{className:"bg-muted/50 rounded-md p-4 font-mono text-sm space-y-1","data-testid":"text-credits-preview",children:[Xe()&&e.jsx("div",{"data-testid":"text-credit-couple",children:Xe()}),Ze(d||[]).map(t=>{const a=t.instagram?`@${t.instagram.replace(/^@/,"")}`:Me(t);return e.jsx(Os,{vendor:t,categoryLabel:qe(t.category),displayHandle:a,canEdit:we,selfProfile:Ce,onDismissSelf:t.isSelf?ps:void 0},t.isSelf?"self":t.id)})]}),e.jsx("p",{className:"text-sm text-muted-foreground mt-5 mb-3",children:"For your wedding website, names linked to vendor sites:"}),e.jsx("div",{className:"bg-muted/50 rounded-md p-4 text-sm space-y-1","data-testid":"text-website-preview",children:Ze(d||[]).map(t=>e.jsx(Os,{vendor:t,categoryLabel:qe(t.category),displayHandle:t.name||Me(t)||"Add website",canEdit:we,selfProfile:Ce,onDismissSelf:t.isSelf?ps:void 0,field:"website"},t.isSelf?"self-web":`web-${t.id}`))}),e.jsx("div",{className:"mt-3",children:e.jsxs(kn,{children:[e.jsxs(C,{variant:"ghost",className:Ot,onClick:$a,"data-testid":"button-copy-credits-inline",children:[e.jsx(En,{className:"w-3 h-3 mr-1.5"}),"Copy credits"]}),e.jsxs(C,{variant:"ghost",className:Ot,onClick:Ia,"data-testid":"button-copy-website-inline",children:[e.jsx(Wt,{className:"w-3 h-3 mr-1.5"}),"Copy for website"]}),e.jsxs(C,{variant:"ghost",className:Ot,onClick:Sa,"data-testid":"button-copy-emails-inline",children:[e.jsx(pt,{className:"w-3 h-3 mr-1.5"}),"Copy all emails"]})]})})]})]}),Y&&e.jsxs(Ee,{className:"border-primary/20 bg-primary/5 mb-6",children:[e.jsx(dt,{className:"pb-3",children:e.jsxs(Mt,{className:"flex items-center gap-2 text-lg font-display",children:[e.jsx(Ve,{className:"h-5 w-5 text-primary"}),"Request Vendor Information"]})}),e.jsxs(Fe,{className:"space-y-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Ask the couple to add their wedding vendors. They'll receive an email with a direct link to this page."}),e.jsxs("div",{className:"flex items-center gap-3 py-2 px-3 rounded-lg bg-background border",children:[e.jsx(Qs,{checked:cs?.enabled??!1,onCheckedChange:t=>ms.mutate(t),disabled:ms.isPending,"data-testid":"switch-vendor-info-auto-send"}),e.jsxs("div",{children:[e.jsx(T,{className:"text-sm font-medium cursor-pointer",children:"Auto-send to all couples"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:"Automatically sends this request to all your current and future couples"})]}),cs?.enabled&&e.jsx(J,{variant:"secondary",className:"text-[10px] shrink-0 ml-auto",children:"Active"})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(U,{onClick:()=>{hs(!1),je(!0)},size:"sm","data-testid":"button-request-vendor-info",children:[e.jsx(Ve,{className:"h-3.5 w-3.5 mr-2"}),"Send Request"]}),Ct&&Ct.length>1&&e.jsxs(C,{onClick:()=>{hs(!0),Ge([]),je(!0)},variant:"outline",size:"sm","data-testid":"button-request-vendor-info-bulk",children:[e.jsx(lt,{className:"h-3.5 w-3.5 mr-2"}),"Send to Multiple"]})]})]})]}),e.jsx(ee,{open:xa,onOpenChange:je,children:e.jsxs(te,{className:"max-w-md",children:[e.jsx(se,{children:e.jsx(ae,{className:"font-display text-xl font-normal",children:xs?"Send Vendor Info Request to Multiple Couples":"Send Vendor Info Request"})}),e.jsx("div",{className:"space-y-4 py-2",children:xs?e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Select the couples you'd like to request vendor information from."}),e.jsx("div",{className:"space-y-2 max-h-60 overflow-y-auto",children:Ct?.map(t=>e.jsxs("label",{className:"flex items-center gap-3 p-2 rounded hover:bg-accent cursor-pointer",children:[e.jsx(mt,{checked:Ae.includes(t.id),onCheckedChange:a=>{Ge(i=>a?[...i,t.id]:i.filter(l=>l!==t.id))},"data-testid":`checkbox-vendor-request-wedding-${t.id}`}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium",children:t.coupleNames||`Wedding #${t.id}`}),t.weddingDate&&e.jsx("p",{className:"text-xs text-muted-foreground",children:t.weddingDate})]})]},t.id))}),e.jsxs(U,{onClick:()=>{je(!1),fs.openPreview()},disabled:Ae.length===0,className:"w-full","data-testid":"button-confirm-vendor-request-bulk",children:[e.jsx(Ke,{className:"h-4 w-4 mr-2"}),"Preview & Send to ",Ae.length," Couple",Ae.length!==1?"s":""]})]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Send a request to the couple asking them to add their wedding vendor details. They'll receive an email notification."}),e.jsxs(U,{onClick:()=>
10{W?.id&&(je(!1),gs.openPreview())},disabled:!W?.id,className:"w-full","data-testid":"button-confirm-vendor-request",children:[e.jsx(Ke,{className:"h-4 w-4 mr-2"}),"Preview & Send"]})]})})]})}),d&&d.some(t=>t.totalCost)&&(()=>{const t=d.reduce((q,H)=>q+(H.totalCost||0),0),a=d.reduce((q,H)=>q+(H.amountPaid||0),0),i=t-a,l=d.filter(q=>q.totalCost&&q.totalCost>0),$=l.filter(q=>q.paymentStatus==="paid").length;return e.jsx(Ee,{className:"mb-6","data-testid":"card-vendor-cost-summary",children:e.jsx(Fe,{className:"pt-5 pb-4",children:e.jsxs("div",{className:"flex flex-wrap gap-6 sm:gap-10 items-center",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] tracking-[0.2em] uppercase text-muted-foreground/70 mb-1",children:"Total Vendor Costs"}),e.jsx("p",{className:"text-2xl font-display font-light","data-testid":"text-total-vendor-cost",children:x(t)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] tracking-[0.2em] uppercase text-muted-foreground/70 mb-1",children:"Total Paid"}),e.jsx("p",{className:"text-2xl font-display font-light text-green-600 dark:text-green-400","data-testid":"text-total-paid",children:x(a)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] tracking-[0.2em] uppercase text-muted-foreground/70 mb-1",children:"Remaining Balance"}),e.jsx("p",{className:`text-2xl font-display font-light ${i>0?"text-amber-600 dark:text-amber-400":"text-green-600 dark:text-green-400"}`,"data-testid":"text-total-balance",children:x(i)})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] tracking-[0.2em] uppercase text-muted-foreground/70 mb-1",children:"Vendors Paid"}),e.jsxs("p",{className:"text-2xl font-display font-light","data-testid":"text-vendors-paid-count",children:[$,"/",l.length]})]})]})})})})(),e.jsx(_n,{weddingId:W?.id,canRespond:rn(me)}),e.jsx(qa,{sensors:D,collisionDetection:Ra,onDragStart:t=>f(Number(t.active.id)),onDragEnd:K,onDragCancel:()=>f(null),children:e.jsx(Oa,{items:L.map(t=>t.id),strategy:La,children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6",children:[L?.map(t=>
10e.jsx(tr,{vendor:t,canEdit:we,canEmail:yt,canVendorEditOwn:ia,setInviteVendor:Te,setInviteMessage:ge,setEmailVendor:rs,setAccessVendor:is,openEditDialog:Ca,deleteVendor:p},t.id)),L?.length===0&&!o&&e.jsx("div",{className:"col-span-full",children:e.jsx(fn,{icon:Fn,title:"No vendors listed yet",description:"Add your wedding dream team to get started.",variant:"soft",testId:"empty-state-vendors"})})]})})}),vt&&e.jsx(ar,{vendor:vt,open:!!vt,onOpenChange:t=>{t||rs(null)}}),e.jsx(ee,{open:!!Z,onOpenChange:t=>{t||(Te(null),ge(""))},children:e.jsxs(te,{children:[e.jsx(se,{children:e.jsx(ae,{children:"Send Profile Invite"})}),Z&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-muted-foreground",children:["Send ",e.jsx("span",{className:"font-medium text-foreground",children:Z.name})," an email with a link to complete their vendor profile. They can fill in how they'd like to be credited, their contact info, and social media."]}),e.jsxs("div",{className:"text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Sending to: "}),e.jsx("span",{className:"font-medium",children:Z.email})]}),Z.inviteSentAt&&e.jsxs("div",{className:"text-xs text-muted-foreground flex items-center gap-1",children:[e.jsx(ut,{className:"w-3 h-3"}),"Previously sent ",Ls(Z.inviteSentAt)]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(T,{htmlFor:"invite-message",children:"Personal Message (optional)"}),e.jsx(zs,{field:"vendor_email_body",weddingId:Z.weddingId??void 0,currentText:He,onTextGenerated:t=>ge(t.slice(0,Ds)),context:{recipientName:`${Z.name}${Z.category?` (${Z.category})`:""}`,question:"This is a short personal welcome inside an invitation email that gives the vendor access to the wedding's vendor portal."},mode:"both",size:"xs"})]}),e.jsx(rt,{id:"invite-message",placeholder:"Hi! We're so excited to have you as part of our wedding...",value:He,onChange:t=>ge(t.target.value),className:"resize-none mt-1.5",rows:3,maxLength:Ds,"data-testid":"input-invite-message"})]}),e.jsxs("div",{className:"flex gap-2 justify-end",children:[e.jsx(C,{variant:"outline",onClick:()=>Te(null),"data-testid":"button-cancel-invite",children:"Cancel"}),e.jsxs(U,{onClick:vs.openPreview,"data-testid":"button-preview-invite",children:[e.jsx(Ke,{className:"w-4 h-4 mr-1.5"})," Preview & Send"]})]})]})]})}),vs.modal,bs.modal,gs.modal,fs.modal,bt&&e.jsx(Zn,{vendor:bt,open:!!bt,onOpenChange:t=>{t||is(null)},weddingQueryParam:I}),Ns.modal]})}function sr(s){return s<1024?s+" B":s<1024*1024?(s/1024).toFixed(1)+" KB":(s/(1024*1024)).toFixed(1)+" MB"}function ar({vendor:s,open:o,onOpenChange:d}){const[x,m]=n.useState(""),[N,u]=n.useState(""),[w,y]=n.useState([]),[k,r]=n.useState(null),[v,E]=n.useState(!1),[p,P]=n.useState([]),[g,S]=n.useState([]),h=n.useRef(null),{toast:f}=re(),{weddingQueryParam:D}=Ue(),{user:L}=Ks(),K=[{key:"timeline",label:"Timeline",icon:ot},{key:"day-of-contacts",label:"Contacts",icon:xt},{key:"venue-details",label:"Venue",icon:Ut}];async function c(b,M){r(b);try{const V=new URLSearchParams;if(V.set("type",b),M&&V.set("filterRole",M),D){const Ne=new URLSearchParams(D.startsWith("?")?D.slice(1):D).get("weddingId");Ne&&V.set("weddingId",Ne)}const _=await F("GET",`/api/vendor-email-templates?${V}`);if(!_.ok)throw new Error("Failed to load template");const z=await _.json();if(z.empty){f({title:"No Data",description:z.message,variant:"destructive"});return}m(z.subject),u(z.body),z.availableRoles&&P(z.availableRoles)}catch{f({title:"Couldn’t complete that",description:"Could not load template",variant:"destructive"})}finally{r(null)}}const I=Q({mutationFn:async()=>{const b=new FormData;return b.append("subject",x),b.append("body",N),w.forEach(V=>b.append("attachments",V)),(await ln("POST",`/api/vendors/${s.id}/email`+D,b)).json()},onSuccess:b=>{f({title:"Sent",description:b.message}),m(""),u(""),y([]),d(!1)},onError:b=>{f({title:"Couldn’t complete that",description:b.message,variant:"destructive"})}});function G(b){const M=Array.from(b.target.files||[]),V=[...w,...M].slice(0,5);if(V.reduce((z,De)=>z+De.size,0)>10*1024*1024){f({title:"Too large",description:"Total attachments must be under 10 MB",variant:"destructive"});return}y(V),h.current&&(h.current.value="")}function le(b){y(M=>M.filter((V,_)=>_!==b))}return e.jsxs(ee,{open:o,onOpenChange:b=>{b||y([]),d(b)},children:[e.jsxs(te,{className:"sm:max-w-lg",children:[e.jsx(se,{children:e.jsxs(ae,{className:"font-display",children:["Email ",s.name]})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(pt,{className:"w-4 h-4 shrink-0"}),e.jsx("span",{className:"truncate","data-testid":"text-email-vendor-recipient",children:s.email})]}),e.jsxs("div",{children:[e.jsx(T,{className:"text-sm text-muted-foreground mb-1 block",children:"Qu
10ick Fill"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:K.map(b=>e.jsxs(C,{variant:"outline",size:"sm",onClick:()=>{b.key!=="timeline"&&P([]),S([]),c(b.key)},disabled:k!==null,"data-testid":`button-template-${b.key}`,children:[k===b.key?e.jsx(X,{className:"w-3.5 h-3.5 mr-1.5 animate-spin"}):e.jsx(b.icon,{className:"w-3.5 h-3.5 mr-1.5"}),b.label]},b.key))}),p.length>0&&e.jsxs("div",{className:"mt-2 space-y-1.5",children:[e.jsx("span",{className:"text-[10px] text-muted-foreground block",children:"Filter by role:"}),e.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[e.jsx("button",{onClick:()=>{S([]),c("timeline")},className:`text-[10px] px-2 py-1 rounded border transition-colors ${g.length===0?"border-primary bg-primary/10 text-primary":"border-border/50 text-muted-foreground hover:border-primary/40"}`,"data-testid":"role-filter-all",children:"Full timeline"}),p.map(b=>{const M=g.includes(b);return e.jsx("button",{onClick:()=>{const V=M?g.filter(_=>_!==b):[...g,b];S(V),c("timeline",V.length>0?V.join(","):void 0)},className:`text-[10px] px-2 py-1 rounded border transition-colors ${M?"border-primary bg-primary/10 text-primary":"border-border/50 text-muted-foreground hover:border-primary/40"}`,"data-testid":`role-filter-${b}`,children:b},b)})]})]})]}),e.jsxs("div",{children:[e.jsx(T,{className:"text-sm text-muted-foreground mb-1 block",children:"Subject"}),e.jsx(O,{placeholder:"e.g. Quick question about our wedding day",value:x,onChange:b=>m(b.target.value),"data-testid":"input-email-vendor-subject"})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx(T,{className:"text-sm text-muted-foreground",children:"Message"}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(zs,{field:"vendor_email_body",weddingId:s.weddingId??void 0,currentText:N,onTextGenerated:u,context:{recipientName:`${s.name}${s.category?` (${s.category})`:""}`},mode:"both",size:"xs"}),e.jsx(vn,{onInsert:b=>u(M=>M?M+`
11
12`+b:b)})]})]}),e.jsx(rt,{placeholder:`Write your message to ${s.name}...`,value:N,onChange:b=>u(b.target.value),className:"resize-none min-h-[140px]",rows:5,"data-testid":"input-email-vendor-body"})]}),e.jsxs("div",{children:[e.jsx("input",{ref:h,type:"file",multiple:!0,className:"hidden",onChange:G,accept:".pdf,.doc,.docx,.jpg,.jpeg,.png,.gif,.xlsx,.xls,.csv,.txt","data-testid":"input-email-vendor-files"}),e.jsxs(C,{type:"button",variant:"outline",size:"sm",onClick:()=>h.current?.click(),disabled:w.length>=5,"data-testid":"button-attach-file",children:[e.jsx(Ys,{className:"w-4 h-4 mr-2"}),"Attach Files",w.length>0&&e.jsxs("span",{className:"ml-1 text-muted-foreground",children:["(",w.length,"/5)"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Up to 5 files, 10 MB total"})]}),w.length>0&&e.jsx("div",{className:"space-y-1.5","data-testid":"attachment-list",children:w.map((b,M)=>e.jsxs("div",{className:"flex items-center gap-2 text-sm bg-muted/50 rounded-md px-3 py-1.5",children:[e.jsx(ct,{className:"w-4 h-4 text-muted-foreground shrink-0"}),e.jsx("span",{className:"truncate flex-1","data-testid":`attachment-name-${M}`,children:b.name}),e.jsx("span",{className:"text-xs text-muted-foreground shrink-0",children:sr(b.size)}),e.jsx(C,{type:"button",variant:"ghost",size:"icon","aria-label":"Remove attachment",className:"h-6 w-6 shrink-0",onClick:()=>le(M),"data-testid":`button-remove-attachment-${M}`,children:e.jsx(Qt,{className:"w-3 h-3"})})]},M))}),e.jsxs("div",{className:"flex justify-end gap-2 pt-2",children:[e.jsx(C,{variant:"outline",onClick:()=>d(!1),"data-testid":"button-cancel-email-vendor",children:"Cancel"}),e.jsxs(U,{onClick:()=>E(!0),disabled:!x.trim()||!N.trim()||I.isPending,"data-testid":"button-send-email-vendor",children:[e.jsx(Ke,{className:"w-4 h-4 mr-2"}),"Preview & Send"]})]})]})]}),e.jsx(yn,{open:v,onOpenChange:E,emailType:"vendor_blast",params:{subject:x,body:N,senderName:L&&[L.firstName,L.lastName].filter(Boolean).join(" ")||"Your Planner"},recipientEmail:s.email||void 0,onConfirmSend:()=>{I.mutate(),E(!1)},isSending:I.isPending,title:"Preview Email to Vendor"})]})}
12export{ho 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.