PageSourceSearch

https://fyra.life/assets/PlaceSearch-DVf6FLH1.js

js fyra.life collected 2026-10-02 02:00:22 UTC 13,068 bytes, 1 lines download raw bytes

1import{u as ee,b as re,a as te,r as m,s as n,j as t,B as P,X as oe}from"./index-CEISlULX.js";import{u as ae}from"./useHomeRegion-BAQ18bpq.js";import{g as se}from"./regions-mxAOIkNk.js";import{I as ne}from"./input-CaLoYHgx.js";import{triggerPlacePlaceholder as ie}from"./triggerPlacePlaceholder-CN-rDzJR.js";import{i as H}from"./isL1Taxonomy-CfvEgPBW.js";import{u as le}from"./useDefaultShareVisibility-CJnViBYM.js";import{A as ce}from"./arrow-left-Dt5WA4Nk.js";import{C as de}from"./check-BFjtj0TV.js";import{L as ue}from"./loader-circle-C0qiwHXp.js";import{P as _e}from"./plus-CMUH1C5J.js";const Se=()=>{const V=ee(),[U]=re(),{toast:S}=te(),[j,R]=m.useState(null),{defaultVisibility:G}=le(j),[b,$]=m.useState(""),[E,T]=m.useState("__pending__"),{homeRegion:C}=ae(),[q,L]=m.useState([]),[Q,A]=m.useState(!1),[F,M]=m.useState(null),[W,k]=m.useState(new Set),[me,X]=m.useState({}),[O,Y]=m.useState({}),[D,J]=m.useState({}),B=e=>{const a=(e.address||"").trim();if(a.length>0)return a;const i=(e.state||e.region||"").trim();return[e.city,i,e.country].map(d=>(d||"").trim()).filter(Boolean).join(", ")};m.useEffect(()=>{const{data:{subscription:e}}=n.auth.onAuthStateChange((a,i)=>{R((i==null?void 0:i.user)??null)});return n.auth.getSession().then(({data:{session:a}})=>{R((a==null?void 0:a.user)??null)}),()=>e.unsubscribe()},[]),m.useEffect(()=>{E==="__pending__"&&T(C||"us_canada")},[C]),m.useEffect(()=>{(async()=>{if(!j){k(new Set);return}try{const{data:a}=await n.from("user_vault_tastes").select("entity_id").eq("user_id",j.id).eq("entity_type","place");if(!a||a.length===0){k(new Set);return}const i=a.map(s=>parseInt(s.entity_id,10)).filter(s=>!isNaN(s));if(i.length===0){k(new Set);return}const{data:d}=await n.from("corpus_places").select("provider_place_id").in("id",i),y=new Set((d||[]).map(s=>s.provider_place_id).filter(s=>s!==null));k(y)}catch(a){console.error("Error loading saved places:",a)}})()},[j]),m.useEffect(()=>{(async()=>{try{const{data:a,error:i}=await n.from("api_here_categories").select("category_id, name, l1_name"),d={};if(i)console.error("Error loading api_here_categories:",i);else if(a&&Array.isArray(a))for(const h of a){const u=h.category_id,r=h.name??null,c=h.l1_name??null;r&&c&&c!==r?d[u]=`${r} (${c})`:r?d[u]=r:c&&(d[u]=c)}const{data:y,error:s}=await n.from("taxonomy_food_styles_view").select("here_food_type_code, style_label"),_={};if(s)console.error("Error loading taxonomy_food_styles_view:",s);else if(y&&Array.isArray(y))for(const h of y){const u=h.here_food_type_code,r=h.style_label;!u||!r||(_[u]||(_[u]=[]),_[u].includes(r)||_[u].push(r))}const l={},{data:f,error:I}=await n.from("map_here_to_taxonomy_place").select("here_category_id, tastex_category_id");if(I)console.error("Error loading map_here_to_taxonomy_place:",I);else if(f&&f.length>0){const{data:h,error:u}=await n.from("ref_taxonomy").select("id, name, level, parent_id").eq("domain","place").eq("is_active",!0).order("name");if(u)console.error("Error loading ref_taxonomy (place):",u);else if(h&&Array.isArray(h)){const r=new Map;h.forEach(o=>{o.level===1&&r.set(o.id,o.name)});const c=new Map;h.forEach(o=>{o.level===2?c.set(o.id,{level_2:r.get(o.parent_id)??null,level_3:o.name??null}):o.level===1&&c.set(o.id,{level_2:o.name??null,level_3:o.name??null})}),f.forEach(o=>{const v=o.here_category_id,w=o.tastex_category_id,p=c.get(w);if(!p)return;const x=p.level_3??null;x&&(l[v]=x)})}}X(d),Y(_),J(l)}catch(a){console.error("Error loading HERE/TasteX lookup tables:",a)}})()},[]),m.useEffect(()=>{const e=async()=>{if(!b.trim()||E==="__pending__"){L([]);return}A(!0);try{const{data:i,error:d}=await n.functions.invoke("search-places",{body:{query:b,country:E,home_region:C}});if(d)throw d;const y=i&&i.places||[];L(y)}catch(i){console.error("Search error:",i),S({description:i.message||"Failed to search for places",variant:"destructive"})}finally{A(!1)}};b.trim().length>=2&&A(!0);const a=setTimeout(e,250);return()=>clearTimeout(a)},[b,E,S]);const K=async(e,a,i=!1)=>{var d,y;if(!j){S({description:"You must be logged in to save places",variant:"destructive"});return}M(`place-${a}-${i?"review":"normal"}`);try{let s=null;const _=e.websites&&e.websites.length>0?e.websites[0]:null;if(_)try{const{data:r}=await n.functions.invoke("capture-thumbnail",{body:{url:_}});s=(r==null?void 0:r.imageUrl)||null}catch(r){console.error("Failed to capture thumbnail:",r)}let l=null;if(e.here_place_id){const r=e.here_place_id,c={provider:"HERE",provider_place_id:r,here_id:r,name:e.name,city:e.city,region:e.region??null,country_code:e.country_code??null,state:e.state,country:e.country},{data:o,error:v}=await n.from("corpus_places").upsert(c,{onConflict:"provider,provider_place_id"}).select("id").maybeSingle();if(v)throw console.error("Error upserting into corpus_places:",v),v;if(l=(o==null?void 0:o.id)??null,l){const x=e.address_line1&&e.address_line1.trim().length>0?e.address_line1:e.address||null,g=e.here_category_ids??e.category_ids??[],N=e.here_food_type_codes??e.food_type_codes??[],Z={corpus_place_id:l,address_line1:x,address_line2:e.address_line2??null,postcode:e.postcode??null,lat:e.latitude,lng:e.longitude,phone:null,website_url:_,image_url:s,primary_category_id:e.primary_category_id??(g.length>0?g[0]:null),here_food_type_codes:N,here_category_ids:g,primary_food_type_code:e.primary_food_type_code??(N.length>0?N[0]:null)},{error:z}
1=await n.from("corpus_places_here_ephemeral").upsert(Z,{onConflict:"corpus_place_id"});if(z)throw console.error("Error upserting into corpus_places_here_ephemeral:",z),z}const w=e.here_category_ids??e.category_ids??[];if(l&&w.length>0){const x=w.map(N=>({corpus_place_id:l,here_category_id:N})),{error:g}=await n.from("api_here_allcategoriesbyplace").upsert(x,{onConflict:"corpus_place_id,here_category_id"});if(g)throw console.error("Error upserting api_here_allcategoriesbyplace:",g),g}const p=e.here_food_type_codes??e.food_type_codes??[];if(l&&p.length>0){const x=p.map(N=>({corpus_place_id:l,here_food_type_code:N})),{error:g}=await n.from("api_here_allfoodtypesbyplace").upsert(x,{onConflict:"corpus_place_id,here_food_type_code"});if(g)throw console.error("Error upserting api_here_allfoodtypesbyplace:",g),g}}if(!l)throw new Error("Failed to create corpus_places entry for this place");let f=null;const I=e.primary_category_id??((d=e.here_category_ids)==null?void 0:d[0])??((y=e.category_ids)==null?void 0:y[0])??null;if(I){const{data:r}=await n.from("map_here_to_taxonomy_place").select("taxonomy_id, tx_category_id").eq("here_category_id",I).maybeSingle();f=(r==null?void 0:r.taxonomy_id)??(r==null?void 0:r.tx_category_id)??null,H(f)&&(f=null)}if(!f){const r=e.here_category_ids??e.category_ids??[];if(r.length>0){const{data:c}=await n.from("map_here_to_taxonomy_place").select("taxonomy_id, tx_category_id").in("here_category_id",r).limit(1),o=c==null?void 0:c[0];f=(o==null?void 0:o.taxonomy_id)??(o==null?void 0:o.tx_category_id)??null,H(f)&&(f=null)}}if(!f&&l)try{const r=[e.address,e.city,e.state,e.country].filter(Boolean).join(", "),c=e.here_category_ids??e.category_ids??[],o=[];if(c.length){const{data:p}=await n.from("api_here_categories").select("name").in("category_id",c);p!=null&&p.length&&o.push(...p.map(x=>x.name))}const{data:v}=await n.functions.invoke("categorize-place",{body:{name:e.name,address:r,here_categories:o}}),w=(v==null?void 0:v.taxonomy_id)??null;w&&(f=w,await n.from("corpus_places_allcategories").upsert({corpus_place_id:l,taxonomy_id:w,is_primary:!0,source:"ai_categorize_on_save"},{onConflict:"corpus_place_id,taxonomy_id"}))}catch(r){console.warn("categorize-place failed, saving without taxonomy:",r)}const{data:h}=await n.from("user_vault_tastes").select("id").eq("user_id",j.id).eq("entity_id",String(l)).maybeSingle();if(h){S({title:"Already in your Vault"});return}const{error:u}=await n.from("user_vault_tastes").upsert({user_id:j.id,entity_type:"place",entity_id:String(l),source:"manual_add_place",share_visibility:G,taxonomy_id:f},{onConflict:"user_id,entity_type,entity_id"});if(u)throw console.error("Save error (user_vault_tastes):",u),u;ie(l,e.name,null,[e.city,e.state,e.country].filter(Boolean).join(", "));try{const r=B(e);await n.functions.invoke("match-google-place-auth",{body:{place_id:l,name:e.name,address:r,lat:e.latitude,lng:e.longitude,match_source:"google_on_save_auth_v1"}})}catch(r){console.error("Google match failed (non-blocking):",r)}try{await n.functions.invoke("match-apple-place-auth",{body:{place_id:l,name:e.name,address:B(e),lat:e.latitude,lng:e.longitude,match_source:"apple_on_save_auth_v1"}})}catch(r){console.error("Apple match failed (non-blocking):",r)}e.here_place_id&&k(r=>new Set(r).add(e.here_place_id)),S({description:"Saved to your Vault"})}catch(s){console.error("Save error:",s),S({description:s.message||"Failed to save place",variant:"destructive"})}finally{M(null)}};return t.jsxs("div",{className:"h-screen flex flex-col overflow-hidden bg-background",children:[t.jsxs("header",{className:"pt-[env(safe-area-inset-top)] border-b border-border px-4 py-2 flex justify-between items-center gap-4 flex-shrink-0",children:[t.jsx("div",{className:"flex items-center gap-2 flex-shrink-0",children:t.jsx(P,{variant:"ghost",size:"icon",className:"h-9 w-9",onClick:()=>V(U.get("returnTo")||"/vault?type=place"),children:t.jsx(ce,{className:"h-5 w-5"})})}),t.jsx("div",{className:"flex items-center gap-2"})]}),t.jsx("div",{className:"flex-1 overflow-auto",children:t.jsxs("div",{className:"max-w-4xl mx-auto px-6 py-8",children:[t.jsx("h2",{className:"text-2xl md:text-3xl font-bold text-foreground text-center mb-6",children:"Where do you go?"}),t.jsxs("div",{className:"mt-12 relative",children:[t.jsxs("div",{className:"flex flex-col gap-4 mb-4",children:[t.jsxs("div",{className:"flex gap-2",children:[t.jsx(P,{variant:E!=="INTL"?"default":"outline",size:"sm",onClick:()=>T(C||"us_canada"),className:"flex-1",children:se(C||"us_canada")}),t.jsx(P,{variant:E==="INTL"?"default":"outline",size:"sm",onClick:()=>T("INTL"),className:"flex-1",children:"International"})]}),t.jsxs("div",{className:"relative",children:[t.jsx(ne,{placeholder:"Search for your favorite place here",value:b,onChange:e=>$(e.target.value),className:`text-lg py-6 px-6 rounded-2xl border-2 focus-visible:ring-offset-4 ${b?"pr-14":""}`}),b&&t.jsx("button",{type:"button","aria-label":"Clear search",onClick:()=>{$(""),L([])},className:"absolute right-4 top-1/2 -translate-y-1/2 h-8 w-8 rounded-full flex items-center justify-center text-muted-foreground hover:text-foreground hover:bg-muted",children:t.jsx(oe,{className:"h-5 w-5"})})]})]}),b.trim()&&q.length>0&&t.jsx("div",{className:"mt-4 bg-card border border-border rounded-2xl shadow-lg max-h-96 overflow-y-auto",children:Q?t.jsx("div",{className:"p-8 text-center text-muted-foreground",children:"Searching..."}):t.jsx("div",{className:"p-2",children:q.map((e,a)=>{const i=e.here_category_ids??e.category_ids??[],d=e.here_food_type_codes??e.food_type_codes??[],y=e.here_place_id?W.has(e.here_place_id):!1;return t.jsxs("div",{className:"flex items-start justify-between gap-3 p-2.5 rounded-xl hover:bg-accent/5 transition-colors border-b border-border last:border-b-0",children:[t.jsxs("div",{className:"flex-1 min-w-0 space-y-1.5",children:[t.jsx("h3",{className:"font-semibold text-sm mb-0.5",children:e.name}),t.jsxs("div",{className:"flex flex-wrap gap-1.5 text-[11px] text-muted-foreground",children:[e.city&&t.jsx("span",{children:e.city}),e.state&&t.jsxs("span",{children:["• ",e.state]}),e.country&&t.jsxs("span",{children:["• ",e.country]})]}),i.length>0&&t.jsx("div",{className:"flex flex-wrap gap-1 mt-2 text-[11px] text-muted-foreground",children:i.map(s=>{const _=D[s]??s;return t.jsx("span",{className:"px-2 py-0.5 rounded-full border border-border",children:_},s)})}),d.length>0&&t.jsx("div",{className:"flex flex-wrap gap-1 mt-1 text-[11px] text-muted-foreground",children:d.flatMap(s=>{const _=O[s];return _&&_.length>0?_.map(l=>t.jsx("span",{className:"px-2 py-0.5 rounded-full border border-border",children:l},`${s}-${l}`)):[]})}),e.websites&&e.websites.length>0&&t.jsxs("p",{className:"text-sm text-muted-foreground mt-2",children:["🌐"," ",t.jsx("a",{href:e.websites[0],target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:e.websites[0]})]})]}),t.jsx("div",{className:"flex-shrink-0",children:y?t.jsx(P,{type:"button",variant:"outline",size:"icon",disabled:!0,className:"w-10 h-10 rounded-full border-2 border-green-500 bg-green-500/20 touch-manipulation",title:"Already saved",children:t.jsx(de,{size:18,className:"text-green-600"})}):t.jsx(P,{type:"button",variant:"outline",size:"icon",onClick:s=>{s.preventDefault(),s.stopPropagation(),K(e,a,!1)},disabled:F===`place-${a}-normal`,className:"w-10 h-10 rounded-full border-2 border-green-500 bg-green-500/10 hover:bg-green-500/20 touch-manipulation",title:"Save place",children:F===`place-${a}-normal`?t.jsx(ue,{size:18,className:"text-green-600 animate-spin"}):t.jsx(_e,{size:18,className:"text-green-600"})})})]},`place-${a}`)}
1)})})]})]})})]})};export{Se 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.