1!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},t=(new e.Error).stack;t&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[t]="4ce0d6d1-11e0-478a-a3a8-a5e778840df8",e._sentryDebugIdIdentifier="sentry-dbid-4ce0d6d1-11e0-478a-a3a8-a5e778840df8")}catch(e){}}(),(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[34839],{8525:(e,t,a)=>{"use strict";a.d(t,{U:()=>l});var n=a(89177);function l(){return(0,n.createBrowserClient)("https://hadnfcenpcfaeclczsmm.supabase.co","eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhhZG5mY2VucGNmYWVjbGN6c21tIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjQ1NzcwNzcsImV4cCI6MjA4MDE1MzA3N30.lUKufUuiGg-T-H3zX-oIIBiLwgKRYs_XLlBlK5hFhwo")}},28451:(e,t,a)=>{"use strict";a.d(t,{TourBuilderShell:()=>C});var n=a(95155),l=a(12115),i=a(35299),r=a(84158),s=a(5121);let o=(0,s.A)("megaphone",[["path",{d:"M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z",key:"q8bfy3"}],["path",{d:"M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14",key:"1853fq"}],["path",{d:"M8 6v8",key:"15ugcq"}]]),c=(0,s.A)("plane",[["path",{d:"M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.5-.1 1 .3 1.3L9 12l-2 3H4l-1 1 3 2 2 3 1-1v-3l3-2 3.5 5.3c.3.4.8.5 1.3.3l.5-.2c.4-.3.6-.7.5-1.2z",key:"1v9wt8"}]]);var u=a(45221);let d=(0,s.A)("hard-hat",[["path",{d:"M10 10V5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v5",key:"1p9q5i"}],["path",{d:"M14 6a6 6 0 0 1 6 6v3",key:"1hnv84"}],["path",{d:"M4 15v-3a6 6 0 0 1 6-6",key:"9ciidu"}],["rect",{x:"2",y:"15",width:"20",height:"4",rx:"1",key:"g3x8cw"}]]);var p=a(61654),h=a(69864);let f=[{id:"marketing",label:"Marketing",icon:o,blurb:"Show off a business or property"},{id:"aerial",label:"Aerial",icon:c,blurb:"Drone-captured exteriors"},{id:"wayfinding",label:"Wayfinding",icon:u.A,blurb:"For another site or Google"},{id:"construction",label:"Construction",icon:d,blurb:"Project-linked, plan-pinned"}];function m(e){var t;let{projects:a,onCreated:r}=e,[s,o]=(0,l.useState)(null),[c,u]=(0,l.useState)("marketing"),[d,m]=(0,l.useState)(!1),[v,g]=(0,l.useState)(!1),y=(0,l.useRef)(null);async function x(e){if(e.length&&!v){g(!0);try{var t;let a=await fetch("/api/tours",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:"Untitled tour â ".concat(new Date().toLocaleDateString(void 0,{month:"short",day:"numeric"})),projectId:null!=s?s:void 0,purpose:c})});if(!a.ok)return;let n=await a.json(),l=null!=(t=null==n?void 0:n.data)?t:n;r(l.id,e)}finally{g(!1)}}}return(0,n.jsxs)("div",{className:"space-y-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsx)("div",{className:"flex gap-1.5 rounded-xl border border-[var(--mobile-app-card-border)] bg-white/[0.02] p-1",children:f.map(e=>{let t=e.icon,a=c===e.id;return(0,n.jsxs)("button",{type:"button",title:e.blurb,onClick:()=>u(e.id),className:"flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition ".concat(a?"bg-[color-mix(in_srgb,var(--graphite-primary)_16%,transparent)] text-[var(--graphite-text-header)]":"text-[var(--graphite-muted)] hover:text-[var(--graphite-text-header)]"),children:[(0,n.jsx)(t,{className:"size-3.5"}),e.label]},e.id)})}),(0,n.jsx)("div",{className:"w-64",children:(0,n.jsx)(h.M,{projects:a,selectedProjectId:s,onChange:o})})]}),(0,n.jsx)("input",{ref:y,type:"file",accept:"image/jpeg,image/png",multiple:!0,className:"hidden",onChange:e=>{var t;(null==(t=e.target.files)?void 0:t.length)&&x(e.target.files),e.target.value=""}}),(0,n.jsxs)("div",{onClick:()=>{var e;return null==(e=y.current)?void 0:e.click()},onDragOver:e=>{e.preventDefault(),m(!0)},onDragLeave:()=>m(!1),onDrop:e=>{var t;e.preventDefault(),m(!1),(null==(t=e.dataTransfer.files)?void 0:t.length)&&x(e.dataTransfer.files)},className:"flex cursor-pointer flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed px-6 py-16 text-center transition ".concat(d?"border-[var(--graphite-primary)] bg-[color-mix(in_srgb,var(--graphite-primary)_8%,transparent)]":"border-[var(--mobile-app-card-border)] hover:border-[var(--graphite-primary)]"),children:[v?(0,n.jsx)(i.A,{className:"size-8 animate-spin text-[var(--graphite-primary)]"}):(0,n.jsx)(p.A,{className:"size-8 text-[var(--graphite-muted)]"}),(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-sm font-medium text-[var(--graphite-text-header)]",children:v?"Creating your tourâ¦":"Drop 360\xb0 panoramas here to start a new ".concat(null==(t=f.find(e=>e.id===c))?void 0:t.label.toLowerCase()," tour")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-[var(--graphite-muted)]",children:"or click to choose files â equirectangular JPG/PNG, 2:1 aspect ratio"})]})]})]})}var v=a(42196),g=a(39068);let y=(0,s.A)("file-pen",[["path",{d:"M12.659 22H18a2 2 0 0 0 2-2V8a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v9.34",key:"o6klzx"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M10.378 12.622a1 1 0 0 1 3 3.003L8.36 20.637a2 2 0 0 1-.854.506l-2.867.837a.5.5 0 0 1-.62-.62l.836-2.869a2 2 0 0 1 .506-.853z",key:"zhnas1"}]]);var x=a(71360);function b(e){var t;let{tour:a,onSelect:i,onDelete:r}=e,[s,o]=(0,l.useState)(null),[c,u]=(0,l.useState)(null);return(0,l.useEffect)(()=>{let e=!0;return(async()=>{var t,n,l,i,r;let s=await fetch("/api/tours/".concat(a.id,"/scenes"));if(!s.ok||!e)return;let c=await s.json(),d=null!=(l=null!=(n=null==c?void 0:c.data)?n:c)?l:[];if(!e)return;u(d.length);let p=d.find(e=>"ready"===e.status);if(!p)return;let h=await fetch("/api/tours/".concat(a.id,"/scenes/").concat(p.id,"/image?variant=thumbnail"));if(!h.ok||!e)return;let f=await h.json();o(null!=(r=null==(t=null!=(i=null==f?void 0:f.data)?i:f)?void 0:t.url)?r:null)})(),()=>{e=!1}},[a.id]),(0,n.jsxs)("div",{onClick:i,className:"group relative flex cursor-pointer flex-col overflow-hidden rounded-xl border border-[var(--mobile-app-card-border)] bg-white/[0.02] transition hover:border-[var(--graphite-primary)]",children:[(0,n.jsxs)("div",{className:"relative aspect-video w-full overflow-hidden bg-[var(--graphite-canvas-deep)]",children:[s?(0,n.jsx)("img",{src:s,alt:a.title,className:"h-full w-full object-cover"}):(0,n.jsx)("div",{className:"grid h-full place-items-center text-[var(--graphite-muted)]",children:(0,n.jsx)(v.A,{className:"size-6"})}),(0,n.jsx)("span",{className:"absolute right-2 top-2 flex items-center gap-1 rounded-md px-2 py-0.5 text-[10px] font-medium backdrop-blur ".concat("published"===a.status?"bg-[color-mix(in_srgb,var(--graphite-primary)_28%,black_40%)] text-[var(--graphite-primary)]":"bg-black/50 text-[var(--graphite-muted)]"),children:"published"===a.status?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(g.A,{className:"size-3"})," Published"]}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(y,{className:"size-3"})," Draft"]})})]}),(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2 p-3",children:[(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsx)("p",{className:"truncate text-sm font-medium text-[var(--graphite-text-header)]",children:a.title}),(0,n.jsxs)("p",{className:"text-[11px] text-[var(--graphite-muted)]",children:[null===c?"â¦":"".concat(c," scene").concat(1===c?"":"s")," \xb7 ",(t=a.updated_at)?new Date(t).toLocaleDateString(void 0,{month:"short",day:"numeric"}):""]})]}),(0,n.jsx)("button",{type:"button",onClick:e=>{e.stopPropagation(),r()},className:"shrink-0 rounded p-1.5 text-[var(--graphite-muted)] opacity-0 transition hover:text-red-400 group-hover:opacity-100","aria-label":"Delete tour",children:(0,n.jsx)(x.A,{className:"size-3.5"})})]})]})}function j(e){let{onSelectTour:t}=e,[a,s]=(0,l.useState)([]),[o,c]=(0,l.useState)([]),[u,d]=(0,l.useState)(!0),p=(0,l.useCallback)(async()=>{let e=await fetch("/api/tours");if(e.ok){var t,a;let n=await e.json();s(null!=(a=null!=(t=n.data)?t:n)?a:[])}},[]);async function h(e){(await fetch("/api/tours/".concat(e),{method:"DELETE"})).ok&&s(t=>t.filter(t=>t.id!==e))}return(0,l.useEffect)(()=>{(async()=>{d(!0);try{await Promise.all([p(),fetch("/api/projects").then(e=>e.ok?e.json():{projects:[]}).then(e=>{var t;return c(null!=(t=e.projects)?t:[])})])}finally{d(!1)}})()},[p]),(0,n.jsx)(r._V,{title:"360\xb0 Tours",subtitle:u?void 0:"".concat(a.length," tour").concat(1===a.length?"":"s"),children:(0,n.jsxs)("div",{className:"h-full space-y-6 overflow-y-auto p-5",children:[(0,n.jsx)(m,{projects:o,onCreated:(e,a)=>t(e,a)}),u?(0,n.jsx)("div",{className:"flex justify-center py-12",children:(0,n.jsx)(i.A,{className:"size-5 animate-spin text-[var(--graphite-muted)]"})}):0===a.length?(0,n.jsx)("p",{className:"py-8 text-center text-sm text-[var(--graphite-muted)]",children:"No tours yet â drop your first 360\xb0 panoramas above to get started."}):(0,n.jsx)("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4",children:a.map(e=>(0,n.jsx)(b,{tour:e,onSelect:()=>t(e.id),onDelete:()=>h(e.id)},e.id))})]})})}var w=a(64323),S=a(8525),k=a(29223);function N(e){let{tourId:t,onBack:a,pendingFiles:r}=e,[s,o]=(0,l.useState)(null),[c,u]=(0,l.useState)([]),[d,p]=(0,l.useState)(!0),[h,f]=(0,l.useState)("library"),[m,v]=(0,l.useState)(null),[g,y]=(0,l.useState)(!1),[x,b]=(0,l.useState)(!1),[j,N]=(0,l.useState)(!1),[C,I]=(0,l.useState)(!1),[T,z]=(0,l.useState)([]),[A,_]=(0,l.useState)(null),[P,E]=(0,l.useState)([]),[D,M]=(0,l.useState)(!1),O
1=e=>e&&"object"==typeof e&&"data"in e?e.data:e,L=(0,l.useCallback)(async()=>{let e=await fetch("/api/tours/".concat(t,"/scenes"));if(e.ok){var a;let t=null!=(a=O(await e.json()))?a:[];u(t),v(e=>{var a,n;return null!=(n=null!=e?e:null==(a=t[0])?void 0:a.id)?n:null})}},[t]);(0,l.useEffect)(()=>{(async()=>{p(!0);try{let e=await fetch("/api/tours/".concat(t));e.ok&&o(O(await e.json())),await L()}finally{p(!1)}})()},[t,L]);let{connected:J}=function(e,t){let[a,n]=(0,l.useState)(null),[i,r]=(0,l.useState)(!1),s=(0,l.useRef)(t);return s.current=t,(0,l.useEffect)(()=>{if(!e)return;let t=(0,S.U)(),a=t.channel("tour:".concat(e)).on(w.eO.POSTGRES_CHANGES,{event:"*",schema:"public",table:"tour_processing_jobs",filter:"tour_id=eq.".concat(e)},e=>{var t,a;let l=null!=(a=e.new)?a:e.old;(null==l?void 0:l.id)&&n(l),null==(t=s.current)||t.call(s)}).on(w.eO.POSTGRES_CHANGES,{event:"*",schema:"public",table:"tour_scenes",filter:"tour_id=eq.".concat(e)},()=>{var e;return null==(e=s.current)?void 0:e.call(s)}).subscribe(e=>r(String(e).includes("SUBSCRIBED")));return()=>{t.removeChannel(a)}},[e]),{job:a,connected:i}}(t,L),G=(0,l.useCallback)(async(e,a)=>{var n,l;let i=await fetch("/api/tours/".concat(t,"/scenes/").concat(e,"/image?variant=").concat(a));return i.ok&&null!=(l=null==(n=O(await i.json()))?void 0:n.url)?l:null},[t]);async function B(e){try{let t=await createImageBitmap(e),a={width:t.width,height:t.height};return t.close(),a}catch(e){return{}}}let H=(0,l.useCallback)(async e=>{y(!0);try{for(let a of Array.from(e)){let{width:e,height:n}=await B(a),l=await fetch("/api/tours/".concat(t,"/scenes/upload"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filename:a.name,contentType:a.type,size:a.size,width:e,height:n})});if(!l.ok)continue;let{uploadUrl:i,s3Key:r}=O(await l.json());await fetch(i,{method:"PUT",headers:{"Content-Type":a.type},body:a}),await fetch("/api/tours/".concat(t,"/scenes/complete"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:a.name.replace(/\.\w+$/,""),s3Key:r,size:a.size})})}await L()}finally{y(!1)}},[t,L]),[U,V]=(0,l.useState)(!1);(0,l.useEffect)(()=>{!d&&!U&&(null==r?void 0:r.length)&&(V(!0),H(r))},[d,U,r,H]);let q=(0,l.useCallback)(async(e,a)=>{await fetch("/api/tours/".concat(t,"/scenes/").concat(e),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)}),await L()},[t,L]),R=(0,l.useCallback)(async e=>{await fetch("/api/tours/".concat(t,"/scenes/").concat(e),{method:"DELETE"}),u(t=>t.filter(t=>t.id!==e)),v(t=>t===e?null:t)},[t]),F=(0,l.useCallback)(async(e,a)=>{let n=c.findIndex(t=>t.id===e),l="up"===a?n-1:n+1;if(n<0||l<0||l>=c.length)return;let i=[...c];[i[n],i[l]]=[i[l],i[n]],u(i),await fetch("/api/tours/".concat(t,"/scenes/reorder"),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({sceneIds:i.map(e=>e.id)})})},[c,t]),X=(0,l.useCallback)((e,t)=>{q(e,{initial_yaw:t.yaw,initial_pitch:t.pitch,default_zoom:t.zoom})},[q]),Y=(0,l.useCallback)((e,t)=>{q(e,{view_limits:{center:{yaw:t.yaw,pitch:t.pitch},mode:"restrict",zoom:t.zoom},max_fov:90})},[q]),Z=(0,l.useCallback)(async()=>{if(s){b(!0);try{let e="published"===s.status?"draft":"published",a=await fetch("/api/tours/".concat(t),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:e})});if(a.ok){let e=O(await a.json());o(t=>t?{...t,...e}:t)}}finally{b(!1)}}},[s,t]);(0,l.useEffect)(()=>{"plan"!==h||C||(async()=>{N(!0);try{var e,a;let[n,l]=await Promise.all([fetch("/api/tours/".concat(t,"/plan-sheets")),fetch("/api/tours/".concat(t,"/plan-pins"))]);if(n.ok){let t=O(await n.json());z(null!=(e=t.planSets)?e:[]),_(e=>{var a,n,l,i,r;return null!=(r=null!=e?e:null==(i=t.planSets)||null==(l=i[0])||null==(n=l.sheets)||null==(a=n[0])?void 0:a.id)?r:null})}l.ok&&E(null!=(a=O(await l.json()))?a:[])}finally{N(!1),I(!0)}})()},[h,C,t]);let K=(0,l.useCallback)(async(e,a,n)=>{if(A){M(!0);try{let l=await fetch("/api/tours/".concat(t,"/plan-pins"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({planSheetId:A,sceneId:n,xPct:e,yPct:a})});if(l.ok){let e=O(await l.json());E(t=>[...t,e])}}finally{M(!1)}}},[t,A]),Q=(0,l.useCallback)(async e=>{await fetch("/api/tours/".concat(t,"/plan-pins/").concat(e),{method:"DELETE"}),E(t=>t.filter(t=>t.id!==e))},[t]);return d?(0,n.jsx)("div",{className:"grid h-full place-items-center",children:(0,n.jsx)(i.A,{className:"size-6 animate-spin text-[var(--graphite-muted)]"})}
1):s?(0,n.jsx)(k.E,{title:s.title,tourStatus:s.status,viewerSlug:s.viewer_slug,scenes:c,connected:J,uploading:g,activeTab:h,onTab:f,activeSceneId:m,onSelectScene:v,resolveImageUrl:G,onUpload:H,onDeleteScene:R,onReorder:F,onSetStartView:X,onRestrictView:Y,onPublish:Z,publishing:x,onBack:a,planLoading:j,planSets:T,activePlanSheetId:A,onSelectPlanSheet:_,planPins:P,onPlacePin:K,onDeletePin:Q,creatingPin:D}):(0,n.jsx)("div",{className:"grid h-full place-items-center text-sm text-[var(--graphite-muted)]",children:"Tour not found."})}function C(){let[e,t]=(0,l.useState)(null),[a,i]=(0,l.useState)(void 0);return e?(0,n.jsx)(N,{tourId:e,pendingFiles:a,onBack:()=>{t(null),i(void 0)}}):(0,n.jsx)(j,{onSelectTour:(e,a)=>{t(e),i(a)}})}},34839:(e,t,a)=>{Promise.resolve().then(a.bind(a,28451))},45221:(e,t,a)=>{"use strict";a.d(t,{A:()=>n});let n=(0,a(5121).A)("compass",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z",key:"9ktpf1"}]])},61654:(e,t,a)=>{"use strict";a.d(t,{A:()=>n});let n=(0,a(5121).A)("cloud-upload",[["path",{d:"M12 13v8",key:"1l5pq0"}],["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242",key:"1pljnt"}],["path",{d:"m8 17 4-4 4 4",key:"1quai1"}]])},69864:(e,t,a)=>{"use strict";a.d(t,{M:()=>l});var n=a(95155);function l(e){let{projects:t,selectedProjectId:a,onChange:l}=e;return 0===t.length?null:(0,n.jsxs)("label",{className:"flex flex-col gap-1",children:[(0,n.jsx)("span",{className:"font-mono text-[10px] uppercase tracking-wide text-[var(--graphite-muted)]",children:"Attach to project"}),(0,n.jsxs)("select",{value:null!=a?a:"",onChange:e=>l(e.target.value||null),className:"rounded-lg border border-white/10 bg-white/[0.03] px-3 py-2 text-sm text-[var(--graphite-text-body)]",children:[(0,n.jsx)("option",{value:"",children:"360 Library (not assigned to a project)"}),t.map(e=>(0,n.jsx)("option",{value:e.id,children:e.name},e.id))]})]})}}}]);
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.