4 lines
14 KiB
JavaScript
4 lines
14 KiB
JavaScript
import{f as _,a as v,c as ke}from"../chunks/Bh-96fzJ.js";import{p as da,j as c,m as la,u as ca,g as t,i as o,e as pa,f as va,d as e,s as r,$ as ma,r as a,k as Se,t as z,n as ua}from"../chunks/mO2F3zLa.js";import{d as xa,s as n}from"../chunks/eH5yZvH4.js";import{i as q}from"../chunks/tuD4s8Oc.js";import{h as ba,N as _a,F as fa,r as $,s as R,e as ga,i as ya}from"../chunks/DhvLCtu-.js";import{b as B,a as ha}from"../chunks/Da-hDQCT.js";import{b as wa}from"../chunks/CJrErHKE.js";import{b as Nt}from"../chunks/DBQEMQMg.js";var Pa=_('<meta name="description" content="Seattle/King County house price prediction and visualization tool with ML-powered estimates."/>'),$a=_('<div class="flex items-center justify-center h-64"><div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"></div></div>'),ka=_('<div class="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg mb-4"> </div>'),Sa=_("<option> </option>"),Ca=_('<div class="px-4 py-2 bg-green-100 rounded-lg border border-green-300"><span class="text-xl font-bold text-green-700"> </span></div>'),ja=_('<div class="mt-2 pt-2 border-t border-gray-100"><p class="text-xs font-medium text-gray-600 mb-1">Percentiles</p> <div class="space-y-0.5 text-xs"><div class="flex justify-between"><span class="text-gray-500">25th</span> <span class="font-medium"> </span></div> <div class="flex justify-between"><span class="text-gray-500">75th</span> <span class="font-medium"> </span></div> <div class="flex justify-between"><span class="text-gray-500">90th</span> <span class="font-medium"> </span></div></div></div>'),Ba=_('<div class="space-y-2"><div class="p-2 bg-gray-50 rounded-lg"><p class="text-xs text-gray-500">Total</p> <p class="text-base font-bold text-gray-900"> </p></div> <div class="p-2 bg-blue-50 rounded-lg"><p class="text-xs text-blue-600">Avg</p> <p class="text-base font-bold text-blue-700"> </p></div> <div class="p-2 bg-green-50 rounded-lg"><p class="text-xs text-green-600">Median</p> <p class="text-base font-bold text-green-700"> </p></div> <div class="grid grid-cols-2 gap-1"><div class="p-1 bg-gray-50 rounded text-center"><p class="text-xs text-gray-500">Min</p> <p class="text-xs font-semibold"> </p></div> <div class="p-1 bg-gray-50 rounded text-center"><p class="text-xs text-gray-500">Max</p> <p class="text-xs font-semibold"> </p></div></div> <!></div>'),Ma=_('<div class="mt-3 pt-2 border-t border-gray-100"><p class="text-xs text-gray-500"> <br/> </p></div>'),Fa=_('<div class="grid grid-cols-1 lg:grid-cols-6 gap-4"><div class="lg:col-span-1 space-y-4"><div class="bg-white rounded-xl shadow-sm p-3 border border-gray-100"><h2 class="text-sm font-semibold mb-3 flex items-center gap-1"><span>Filters</span></h2> <div class="space-y-3"><div><span class="block text-xs font-medium text-gray-700 mb-1">Price Range</span> <div class="flex gap-2"><input type="number" class="w-1/2 px-2 py-1 text-sm border rounded" placeholder="Min"/> <input type="number" class="w-1/2 px-2 py-1 text-sm border rounded" placeholder="Max"/></div></div> <div><span class="block text-xs font-medium text-gray-700 mb-1">Bedrooms</span> <div class="flex gap-2"><input type="number" min="0" max="10" class="w-1/2 px-2 py-1 text-sm border rounded"/> <input type="number" min="0" max="10" class="w-1/2 px-2 py-1 text-sm border rounded"/></div></div> <div><span class="block text-xs font-medium text-gray-700 mb-1">Zipcode</span> <select class="w-full px-2 py-1 text-sm border rounded"><option>All Zipcodes</option><!></select></div> <label class="flex items-center gap-2"><input type="checkbox" class="rounded"/> <span class="text-sm text-gray-700">Waterfront only</span></label> <button class="w-full bg-primary-600 text-white py-2 rounded-lg hover:bg-primary-700 transition-colors">Apply Filters</button></div></div> <div class="bg-white rounded-xl shadow-sm p-3 border border-gray-100"><h2 class="text-sm font-semibold mb-3 flex items-center gap-1"><span>Selection</span></h2> <div class="space-y-3"><div><span class="block text-xs font-medium text-gray-700 mb-1"> </span> <input type="range" min="1" max="10" class="w-full"/></div> <div><span class="block text-xs font-medium text-gray-700 mb-1"> </span> <input type="range" min="1" max="6" step="0.5" class="w-full"/></div> <div><span class="block text-xs font-medium text-gray-700 mb-1"> </span> <input type="range" min="500" max="10000" step="100" class="w-full"/></div> <div><span class="block text-xs font-medium text-gray-700 mb-1"> </span> <input type="range" min="0" max="120" class="w-full"/></div></div></div></div> <div class="lg:col-span-4"><div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden"><div class="flex border-b border-gray-200"><button>Map View</button> <button>Distribution</button> <button>Correlations</button></div> <div class="p-4"><div></div> <div></div> <div></div></div> <div class="px-4 py-3 bg-gray-50 border-t border-gray-200 flex items-center justify-between gap-4"><div class="flex items-center gap-4 text-sm text-gray-600"><span> </span> <span> </span> <span> </span> <span> </span></div> <div class="flex items-center gap-3"><button class="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors font-medium">Predict Price</button> <!></div></div></div></div> <div class="lg:col-span-1"><div class="bg-white rounded-xl shadow-sm p-3 border border-gray-100"><h2 class="text-sm font-semibold mb-3 flex items-center gap-1"><span>Stats</span></h2> <!> <!></div></div></div>'),za=_('<div class="min-h-screen bg-gradient-to-b from-slate-50 to-white"><!> <main class="pt-24 pb-16 px-6"><div class="max-w-7xl mx-auto"><div class="mb-6"><a href="/tools" class="text-primary-600 hover:text-primary-700 text-sm mb-2 inline-block">← Back to Tools</a> <h1 class="text-2xl font-bold text-gray-900">House Price Predictor</h1> <p class="text-gray-600 mt-1">Seattle/King County house price prediction and visualization (21,613 houses, 2014-2015)</p></div> <!></div></main> <!></div>');function Ha(Ce,je){da(je,!0);const A="https://cockpit.valuecurve.co/api/v1";let st=c(!1),D=c(""),k=c(null),f=c(la([])),m=c(null),it=c(null),V=c(0),Z=c(8e6),G=c(0),J=c(10),ot=c(!1),W=c(""),E=c(3),N=c(2),H=c(2e3),I=c(10),x=c("map"),Y,Q,X,S=c(null),Ht=c(!1);ca(()=>{if(typeof window<"u"&&!t(Ht)){const s=document.createElement("script");s.src="https://cdn.plot.ly/plotly-2.27.0.min.js",s.onload=()=>{o(S,window.Plotly,!0),o(Ht,!0),Be()},document.head.appendChild(s)}});async function Be(){o(st,!0),o(D,"");try{const s=await fetch(`${A}/house/metadata`);o(k,await s.json(),!0),await It()}catch(s){o(D,s instanceof Error?s.message:"Failed to load data",!0)}finally{o(st,!1)}}async function It(){if(t(S))try{const s=new URLSearchParams;t(V)>0&&s.append("min_price",t(V).toString()),t(Z)<8e6&&s.append("max_price",t(Z).toString()),t(G)>0&&s.append("min_bedrooms",t(G).toString()),t(J)<10&&s.append("max_bedrooms",t(J).toString()),t(ot)&&s.append("waterfront","true"),t(W)&&s.append("zipcode",t(W)),s.append("sample_size","2000");const g=await(await fetch(`${A}/house/data?${s}`)).json();o(f,g.data,!0);const y=await fetch(`${A}/house/statistics`);o(m,await y.json(),!0),setTimeout(()=>{t(x)==="map"?Kt():t(x)==="distribution"?Ot():t(x)==="correlation"&&Ut()},50)}catch(s){o(D,s instanceof Error?s.message:"Failed to update charts",!0)}}function Kt(){var h,b,C,L,K,T;if(!Y||!t(S)||t(f).length===0)return;const s=t(f).map(d=>d.price),p=Math.min(...s),g=Math.max(...s),y={type:"scattermapbox",lat:t(f).map(d=>d.lat),lon:t(f).map(d=>d.long),mode:"markers",marker:{size:t(f).map(d=>Math.max(5,Math.sqrt(d.sqft_living/100))),color:t(f).map(d=>d.price),colorscale:"Viridis",cmin:p,cmax:g,colorbar:{title:"Price ($)",tickformat:",.0f"},opacity:.7},text:t(f).map(d=>`Price: $${d.price.toLocaleString()}<br>Beds: ${d.bedrooms} | Baths: ${d.bathrooms}<br>Sqft: ${d.sqft_living.toLocaleString()}<br>Year Built: ${d.yr_built}<br>Grade: ${d.grade}`),hoverinfo:"text"},ct={mapbox:{style:"open-street-map",center:{lat:((C=(b=(h=t(k))==null?void 0:h.location)==null?void 0:b.center)==null?void 0:C[0])||47.5,lon:((T=(K=(L=t(k))==null?void 0:L.location)==null?void 0:K.center)==null?void 0:T[1])||-122.2},zoom:9},margin:{l:0,r:0,t:30,b:0},title:{text:`King County House Prices (${t(f).length} houses shown)`,font:{size:16}},height:500};t(S).newPlot(Y,[y],ct,{responsive:!0})}async function Ot(){if(!(!Q||!t(S)))try{const p=await(await fetch(`${A}/house/price-distribution?bins=30`)).json(),g={x:p.bin_centers,y:p.counts,type:"bar",marker:{color:p.bin_centers,colorscale:"Viridis"}},y={title:"Price Distribution",xaxis:{title:"Price ($)",tickformat:",.0f"},yaxis:{title:"Count"},margin:{l:60,r:30,t:50,b:60},height:400};t(S).newPlot(Q,[g],y,{responsive:!0})}catch(s){console.error("Failed to render distribution:",s)}}async function Ut(){if(!(!X||!t(S)))try{const p=await(await fetch(`${A}/house/correlation`)).json(),g={z:p.correlation,x:p.columns,y:p.columns,type:"heatmap",colorscale:"RdBu",zmin:-1,zmax:1,colorbar:{title:"Correlation"}},y={title:"Feature Correlation Matrix",margin:{l:100,r:30,t:50,b:100},height:500,xaxis:{tickangle:45},yaxis:{autorange:"reversed"}};t(S).newPlot(X,[g],y,{responsive:!0})}catch(s){console.error("Failed to render correlation:",s)}}async function Me(){try{const s=await fetch(`${A}/house/predict`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({bedrooms:t(E),bathrooms:t(N),sqft:t(H),age:t(I)})});o(it,await s.json(),!0)}catch{o(D,"Prediction failed")}}function nt(s){o(x,s,!0),setTimeout(()=>{s==="map"?Kt():s==="distribution"?Ot():s==="correlation"&&Ut()},100)}function M(s){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:0,maximumFractionDigits:0}).format(s)}var dt=za();ba("1yo8vla",s=>{var p=Pa();va(()=>{ma.title="House Price Predictor | Build with AI"}),v(s,p)});var Vt=e(dt);_a(Vt,{});var lt=r(Vt,2),Zt=e(lt),Fe=r(e(Zt),2);{var ze=s=>{var p=$a();v(s,p)},qe=s=>{var p=ke(),g=Se(p);{var y=h=>{var b=ka(),C=e(b,!0);a(b),z(()=>n(C,t(D))),v(h,b)},ct=h=>{var b=Fa(),C=e(b),L=e(C),K=r(e(L),2),T=e(K),d=r(e(T),2),pt=e(d);$(pt);var Gt=r(pt,2);$(Gt),a(d),a(T);var vt=r(T,2),Jt=r(e(vt),2),mt=e(Jt);$(mt);var Wt=r(mt,2);$(Wt),a(Jt),a(vt);var ut=r(vt,2),xt=r(e(ut),2),bt=e(xt);bt.value=bt.__value="";var De=r(bt);{var Le=i=>{var l=ke(),u=Se(l);ga(u,17,()=>t(k).zipcodes,ya,(w,F)=>{var P=Sa(),tt=e(P,!0);a(P);var et={};z(()=>{n(tt,t(F)),et!==(et=t(F))&&(P.value=(P.__value=t(F))??"")}),v(w,P)}),v(i,l)};q(De,i=>{var l;(l=t(k))!=null&&l.zipcodes&&i(Le)})}a(xt),a(ut);var _t=r(ut,2),Yt=e(_t);$(Yt),ua(2),a(_t);var Te=r(_t,2);Te.__click=It,a(K),a(L);var Qt=r(L,2),Xt=r(e(Qt),2),ft=e(Xt),gt=e(ft),Re=e(gt);a(gt);var te=r(gt,2);$(te),a(ft);var yt=r(ft,2),ht=e(yt),Ee=e(ht);a(ht);var ee=r(ht,2);$(ee),a(yt);var wt=r(yt,2),Pt=e(wt),Ne=e(Pt);a(Pt);var ae=r(Pt,2);$(ae),a(wt);var re=r(wt,2),$t=e(re),He=e($t);a($t);var se=r($t,2);$(se),a(re),a(Xt),a(Qt),a(C);var kt=r(C,2),ie=e(kt),St=e(ie),Ct=e(St);Ct.__click=()=>nt("map");var jt=r(Ct,2);jt.__click=()=>nt("distribution");var oe=r(jt,2);oe.__click=()=>nt("correlation"),a(St);var Bt=r(St,2),Mt=e(Bt);let ne;Nt(Mt,i=>Y=i,()=>Y);var Ft=r(Mt,2);let de;Nt(Ft,i=>Q=i,()=>Q);var le=r(Ft,2);let ce;Nt(le,i=>X=i,()=>X),a(Bt);var pe=r(Bt,2),zt=e(pe),qt=e(zt),Ie=e(qt);a(qt);var At=r(qt,2),Ke=e(At);a(At);var Dt=r(At,2),Oe=e(Dt);a(Dt);var ve=r(Dt,2),Ue=e(ve);a(ve),a(zt);var me=r(zt,2),ue=e(me);ue.__click=Me;var Ve=r(ue,2);{var Ze=i=>{var l=Ca(),u=e(l),w=e(u,!0);a(u),a(l),z(()=>n(w,t(it).formatted_price)),v(i,l)};q(Ve,i=>{t(it)&&i(Ze)})}a(me),a(pe),a(ie),a(kt);var xe=r(kt,2),be=e(xe),_e=r(e(be),2);{var Ge=i=>{var l=Ba(),u=e(l),w=r(e(u),2),F=e(w,!0);a(w),a(u);var P=r(u,2),tt=r(e(P),2),et=e(tt,!0);a(tt),a(P);var Lt=r(P,2),fe=r(e(Lt),2),Ye=e(fe,!0);a(fe),a(Lt);var Tt=r(Lt,2),Rt=e(Tt),ge=r(e(Rt),2),Qe=e(ge,!0);a(ge),a(Rt);var ye=r(Rt,2),he=r(e(ye),2),Xe=e(he,!0);a(he),a(ye),a(Tt);var ta=r(Tt,2);{var ea=j=>{var O=ja(),at=r(e(O),2),U=e(at),rt=r(e(U),2),aa=e(rt,!0);a(rt),a(U);var Et=r(U,2),we=r(e(Et),2),ra=e(we,!0);a(we),a(Et);var Pe=r(Et,2),$e=r(e(Pe),2),sa=e($e,!0);a($e),a(Pe),a(at),a(O),z((ia,oa,na)=>{n(aa,ia),n(ra,oa),n(sa,na)},[()=>M(t(m).percentiles[25]),()=>M(t(m).percentiles[75]),()=>M(t(m).percentiles[90])]),v(j,O)};q(ta,j=>{t(m).percentiles&&j(ea)})}a(l),z((j,O,at,U,rt)=>{n(F,j),n(et,O),n(Ye,at),n(Qe,U),n(Xe,rt)},[()=>{var j;return(j=t(m).count)==null?void 0:j.toLocaleString()},()=>M(t(m).mean),()=>M(t(m).median),()=>M(t(m).min),()=>M(t(m).max)]),v(i,l)};q(_e,i=>{t(m)&&i(Ge)})}var Je=r(_e,2);{var We=i=>{var l=Ma(),u=e(l),w=e(u,!0),F=r(w,2);a(u),a(l),z(()=>{n(w,t(k).region),n(F,` ${t(k).data_period??""}`)}),v(i,l)};q(Je,i=>{t(k)&&i(We)})}a(be),a(xe),a(b),z((i,l)=>{n(Re,`Beds: ${t(E)??""}`),n(Ee,`Baths: ${t(N)??""}`),n(Ne,`Sqft: ${i??""}`),n(He,`Age: ${t(I)??""}yr`),R(Ct,1,`flex-1 px-4 py-3 text-sm font-medium transition-colors
|
|
${t(x)==="map"?"bg-primary-50 text-primary-700 border-b-2 border-primary-600":"text-gray-600 hover:bg-gray-50"}`),R(jt,1,`flex-1 px-4 py-3 text-sm font-medium transition-colors
|
|
${t(x)==="distribution"?"bg-primary-50 text-primary-700 border-b-2 border-primary-600":"text-gray-600 hover:bg-gray-50"}`),R(oe,1,`flex-1 px-4 py-3 text-sm font-medium transition-colors
|
|
${t(x)==="correlation"?"bg-primary-50 text-primary-700 border-b-2 border-primary-600":"text-gray-600 hover:bg-gray-50"}`),ne=R(Mt,1,"",null,ne,{hidden:t(x)!=="map"}),de=R(Ft,1,"",null,de,{hidden:t(x)!=="distribution"}),ce=R(le,1,"",null,ce,{hidden:t(x)!=="correlation"}),n(Ie,`${t(E)??""} bed`),n(Ke,`${t(N)??""} bath`),n(Oe,`${l??""} sqft`),n(Ue,`${t(I)??""}yr old`)},[()=>t(H).toLocaleString(),()=>t(H).toLocaleString()]),B(pt,()=>t(V),i=>o(V,i)),B(Gt,()=>t(Z),i=>o(Z,i)),B(mt,()=>t(G),i=>o(G,i)),B(Wt,()=>t(J),i=>o(J,i)),wa(xt,()=>t(W),i=>o(W,i)),ha(Yt,()=>t(ot),i=>o(ot,i)),B(te,()=>t(E),i=>o(E,i)),B(ee,()=>t(N),i=>o(N,i)),B(ae,()=>t(H),i=>o(H,i)),B(se,()=>t(I),i=>o(I,i)),v(h,b)};q(g,h=>{t(D)?h(y):h(ct,!1)},!0)}v(s,p)};q(Fe,s=>{t(st)?s(ze):s(qe,!1)})}a(Zt),a(lt);var Ae=r(lt,2);fa(Ae),a(dt),v(Ce,dt),pa()}xa(["click"]);export{Ha as component};
|