PageSourceSearch

https://foodflo.app/_app/immutable/nodes/19.c1ABkSMY.js

js foodflo.app collected 2026-10-04 18:48:30 UTC 14,543 bytes, 2 lines download raw bytes

1import"../chunks/CuOgnXdt.js";import{p as J,t as I,a as b,b as V,s as r,c as t,f as C,r as a,g as i,n as te,u as Q,h as W,i as ae,l as A,j as K,o as ce,$ as ue,e as ee}from"../chunks/DXN_rciI.js";import{s as k,d as re,a as z}from"../chunks/Dhs1PqO2.js";import{i as D}from"../chunks/B_reJdki.js";import{e as ne,i as ie}from"../chunks/BkNvGB5n.js";import{h as ve}from"../chunks/BHKw1Ydb.js";import{C as ge}from"../chunks/B1YHaUHM.js";import{t as Z}from"../chunks/C86oACs3.js";import{i as xe}from"../chunks/Cp5e8Dak.js";import{s as R}from"../chunks/DLYa3ulr.js";import{s as se}from"../chunks/BXgnIW9p.js";import{c as me}from"../chunks/Blq4ULkl.js";import{s as N}from"../chunks/Cxz7eCdv.js";import{E as fe}from"../chunks/B5nvRJXo.js";import{I as be}from"../chunks/Dmj4P3c3.js";import{E as oe}from"../chunks/rLEQodsf.js";import{T as he}from"../chunks/Bgom-qwN.js";import{C as _e}from"../chunks/DcC4RmRL.js";import{C as de}from"../chunks/hwl9ja_8.js";import{C as pe}from"../chunks/Bm-kVFU0.js";import{C as we}from"../chunks/CAZBxDLt.js";import{C as ye}from"../chunks/DVFlt4pZ.js";(function(){try{var m=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{};m.SENTRY_RELEASE={id:"e6477a3dc0969721ce553fb9ccfd038301828980"};var e=new m.Error().stack;e&&(m._sentryDebugIds=m._sentryDebugIds||{},m._sentryDebugIds[e]="4a2a4d6e-340b-4073-ac73-940bc2987288",m._sentryDebugIdIdentifier="sentry-dbid-4a2a4d6e-340b-4073-ac73-940bc2987288")}catch{}})();var ke=C('<div class="grid grid-cols-2 sm:grid-cols-4 gap-3"><div class="bg-white rounded-xl border border-stone-200 p-4"><p class="text-xs font-medium text-stone-500 uppercase tracking-wider">Total</p> <p class="text-2xl font-bold text-stone-900 mt-1"> </p></div> <div class="bg-white rounded-xl border border-yellow-200 p-4"><p class="text-xs font-medium text-yellow-600 uppercase tracking-wider">Pending</p> <p class="text-2xl font-bold text-yellow-700 mt-1"> </p></div> <div class="bg-white rounded-xl border border-green-200 p-4"><p class="text-xs font-medium text-green-600 uppercase tracking-wider">Processed</p> <p class="text-2xl font-bold text-green-700 mt-1"> </p></div> <div class="bg-white rounded-xl border border-red-200 p-4"><p class="text-xs font-medium text-red-600 uppercase tracking-wider">Failed</p> <p class="text-2xl font-bold text-red-700 mt-1"> </p></div></div>');function Ce(m,e){J(e,!0);var u=ke(),v=t(u),h=r(t(v),2),o=t(h,!0);a(h),a(v);var x=r(v,2),g=r(t(x),2),E=t(g,!0);a(g),a(x);var d=r(x,2),f=r(t(d),2),T=t(f,!0);a(f),a(d);var _=r(d,2),s=r(t(_),2),w=t(s,!0);a(s),a(_),a(u),I(()=>{k(o,e.stats.total),k(E,e.stats.pending),k(T,e.stats.processed),k(w,e.stats.failed)}),b(m,u),V()}var Ee=C('<div class="flex gap-2 flex-wrap"><a href="/admin/failed-extractions"> </a> <a href="/admin/failed-extractions?status=pending"> </a> <a href="/admin/failed-extractions?status=processed"> </a> <a href="/admin/failed-extractions?status=failed"> </a></div>');function Fe(m,e){J(e,!0);var u=Ee(),v=t(u),h=t(v);a(v);var o=r(v,2),x=t(o);a(o);var g=r(o,2),E=t(g);a(g);var d=r(g,2),f=t(d);a(d),a(u),I(()=>{R(v,1,`px-4 py-2 rounded-xl text-sm font-medium transition-all ${e.currentFilter?"bg-stone-100 text-stone-600 hover:bg-stone-200 hover:text-stone-900":"text-white"}`),se(v,e.currentFilter?"":"background:#E31E24"),k(h,`All (${e.stats.total??""})`),R(o,1,`px-4 py-2 rounded-xl text-sm font-medium transition-all ${e.currentFilter==="pending"?"bg-yellow-500 text-white":"bg-yellow-50 text-yellow-700 hover:bg-yellow-100"}`),k(x,`Pending (${e.stats.pending??""})`),R(g,1,`px-4 py-2 rounded-xl text-sm font-medium transition-all ${e.currentFilter==="processed"?"bg-green-500 text-white":"bg-green-50 text-green-700 hover:bg-green-100"}`),k(E,`Processed (${e.stats.processed??""})`),R(d,1,`px-4 py-2 rounded-xl text-sm font-medium transition-all ${e.currentFilter==="failed"?"bg-red-500 text-white":"bg-red-50 text-red-700 hover:bg-red-100"}`),k(f,`Failed (${e.stats.failed??""})`)}),b(m,u),V()}var Se=C('<p class="text-sm text-stone-700"><span class="font-medium">Contact:</span> </p>'),Pe=C('<p class="text-sm text-red-600 mt-1 bg-red-50 rounded-lg px-3 py-2"> </p>'),Ie=C('<a class="inline-flex items-center gap-1 text-sm text-red-600 hover:text-red-700 mt-1">View Business <!></a>'),Te=C('<button class="px-3 py-1.5 bg-green-100 text-green-700 text-sm font-medium rounded-lg hover:bg-green-200 transition-colors disabled:opacity-50">Mark Processed</button> <button class="px-3 py-1.5 bg-red-100 text-red-700 text-sm font-medium rounded-lg hover:bg-red-200 transition-colors disabled:opacity-50">Mark Failed</button>',1),je=C('<button class="px-3 py-1.5 bg-yellow-100 text-yellow-700 text-sm font-medium rounded-lg hover:bg-yellow-200 transition-colors disabled:opacity-50">Reopen</button>'),Ue=C('<div class="bg-white rounded-2xl border border-stone-200 shadow-sm overflow-hidden"><div class="p-5"><div class="flex items-start gap-4"><button type="button" class="w-20 h-20 rounded-xl bg-stone-100 border border-stone-200 overflow-hidden flex-shrink-0 cursor-pointer hover:ring-2 hover:ring-red-300 transition-all group relative"><img alt="Uploaded menu" class="w-full h-full object-cover" loading="lazy"/> <div class="absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors flex items-center justify-center"><!></div></button> <div class="flex-1 min-w-0"><div class="flex items-center gap-2 mb-1"><span><!> </span> <span class="text-xs text-stone-400"> </span></div> <!> <!> <!></div> <div class="flex items-center gap-2 flex-shrink-0"><a target="_blank" rel="noopener noreferrer" class="px-3 py-1.5 bg-stone-100 text-stone-600 text-sm font-medium rounded-lg hover:bg-stone-200 hover:text-stone-900 transition-colors inline-flex items-center gap-1"><!> Open</a> <!></div></div></div></div>');function Ae(m,e){J(e,!0);function u(n){if(!n)return"—";const c=new Date(n);return isNaN(c.getTime())?"—":c.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric",hour:"2-digit",minute:"2-digit"})}
1function v(n){switch(n){case"pending":return"bg-yellow-100 text-yellow-700";case"processed":return"bg-green-100 text-green-700";case"failed":return"bg-red-100 text-red-700";default:return"bg-stone-100 text-stone-600"}}function h(n){switch(n){case"pending":return pe;case"processed":return de;case"failed":return _e;default:return he}}const o=Q(()=>h(e.extraction.status));var x=Ue(),g=t(x),E=t(g),d=t(E),f=t(d),T=r(f,2),_=t(T);fe(_,{class:"w-5 h-5 text-white opacity-0 group-hover:opacity-100 transition-opacity"}),a(T),a(d);var s=r(d,2),w=t(s),M=t(w),O=t(M);me(O,()=>i(o),(n,c)=>{c(n,{class:"w-3 h-3"})});var G=r(O);a(M);var F=r(M,2),S=t(F,!0);a(F),a(w);var B=r(w,2);{var l=n=>{var c=Se(),U=r(t(c));a(c),I(()=>k(U,` ${e.extraction.contactEmail??""}`)),b(n,c)};D(B,n=>{e.extraction.contactEmail&&n(l)})}var y=r(B,2);{var j=n=>{var c=Pe(),U=t(c,!0);a(c),I(()=>k(U,e.extraction.errorReason)),b(n,c)};D(y,n=>{e.extraction.errorReason&&n(j)})}var p=r(y,2);{var P=n=>{var c=Ie(),U=r(t(c));oe(U,{class:"w-3 h-3"}),a(c),I(()=>N(c,"href",`/admin/businesses/${e.extraction.businessId??""}`)),b(n,c)};D(p,n=>{e.extraction.businessId&&n(P)})}a(s);var Y=r(s,2),q=t(Y),X=t(q);be(X,{class:"w-3.5 h-3.5"}),te(),a(q);var L=r(q,2);{var H=n=>{var c=Te(),U=W(c),$=r(U,2);I(()=>{U.disabled=e.isLoading,$.disabled=e.isLoading}),z("click",U,()=>e.onStatusChange(e.extraction.id,"processed")),z("click",$,()=>e.onStatusChange(e.extraction.id,"failed")),b(n,c)},le=n=>{var c=je();I(()=>c.disabled=e.isLoading),z("click",c,()=>e.onStatusChange(e.extraction.id,"pending")),b(n,c)};D(L,n=>{e.extraction.status==="pending"?n(H):e.extraction.status==="failed"&&n(le,1)})}a(Y),a(E),a(g),a(x),I((n,c)=>{N(f,"src",e.extraction.imageUrl),R(M,1,`inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium ${n??""}`),k(G,` ${e.extraction.status??""}`),k(S,c),N(q,"href",e.extraction.imageUrl)},[()=>v(e.extraction.status),()=>u(e.extraction.createdAt)]),z("click",d,()=>e.onPreview(e.extraction.imageUrl)),b(m,x),V()}re(["click"]);var De=C("<a> </a>"),Me=C('<span class="min-w-[2rem] h-8 flex items-center justify-center text-sm text-stone-400">...</span>'),Le=C('<div class="flex items-center justify-between bg-white rounded-2xl border border-stone-200 shadow-sm px-5 py-3"><p class="text-sm text-stone-500"> </p> <div class="flex items-center gap-1"><a aria-label="Previous page"><!></a> <!> <a aria-label="Next page"><!></a></div></div>');function Re(m,e){J(e,!0);function u(_){const s=new URLSearchParams;e.currentFilter&&s.set("status",e.currentFilter),_>1&&s.set("page",String(_));const w=s.toString();return`/admin/failed-extractions${w?`?${w}`:""}`}var v=Le(),h=t(v),o=t(h);a(h);var x=r(h,2),g=t(x),E=t(g);we(E,{class:"w-4 h-4"}),a(g);var d=r(g,2);ne(d,17,()=>Array.from({length:e.pagination.totalPages},(_,s)=>s+1),ie,(_,s)=>{var w=ae(),M=W(w);{var O=F=>{var S=De(),B=t(S,!0);a(S),I(l=>{N(S,"href",l),R(S,1,`min-w-[2rem] h-8 flex items-center justify-center rounded-lg text-sm font-medium transition-colors ${i(s)===e.pagination.page?"text-white":"text-stone-600 hover:bg-stone-100"}`),se(S,i(s)===e.pagination.page?"background:#E31E24":""),k(B,i(s))},[()=>u(i(s))]),b(F,S)},G=F=>{var S=Me();b(F,S)};D(M,F=>{i(s)===1||i(s)===e.pagination.totalPages||i(s)>=e.pagination.page-1&&i(s)<=e.pagination.page+1?F(O):(i(s)===e.pagination.page-2||i(s)===e.pagination.page+2)&&F(G,1)})}b(_,w)});var f=r(d,2),T=t(f);ye(T,{class:"w-4 h-4"}),a(f),a(x),a(v),I((_,s,w)=>{k(o,`Showing ${(e.pagination.page-1)*e.pagination.pageSize+1}–${_??""} of ${e.pagination.totalItems??""}`),N(g,"href",s),R(g,1,`p-2 rounded-lg transition-colors ${e.pagination.page>1?"hover:bg-stone-100 text-stone-600":"text-stone-300 pointer-events-none"}`),N(f,"href",w),R(f,1,`p-2 rounded-lg transition-colors ${e.pagination.page<e.pagination.totalPages?"hover:bg-stone-100 text-stone-600":"text-stone-300 pointer-events-none"}`)},[()=>Math.min(e.pagination.page*e.pagination.pageSize,e.pagination.totalItems),()=>e.pagination.page>1?u(e.pagination.page-1):void 0,()=>e.pagination.page<e.pagination.totalPages?u(e.pagination.page+1):void 0]),b(m,v),V()}var Ne=C('<div class="fixed inset-0 z-50 bg-black/70 backdrop-blur-sm flex items-center justify-center p-4" role="dialog" aria-label="Image preview" tabindex="-1"><div class="relative max-w-4xl max-h-[90vh]"><img alt="Menu" class="max-w-full max-h-[85vh] rounded-xl shadow-2xl object-contain"/> <div class="mt-3 flex justify-center gap-3"><a target="_blank" rel="noopener noreferrer" class="px-4 py-2 bg-white text-stone-900 text-sm font-medium rounded-xl hover:bg-stone-100 transition-colors inline-flex items-center gap-2"><!> Open in new tab</a> <button type="button" class="px-4 py-2 bg-white/20 text-white text-sm font-medium rounded-xl hover:bg-white/30 transition-colors">Close</button></div></div></div>');function ze(m,e){J(e,!0);var u=Ne(),v=t(u),h=t(v),o=r(h,2),x=t(o),g=t(x);oe(g,{class:"w-4 h-4"}),te(),a(x);var E=r(x,2);a(o),a(v),a(u),I(()=>{N(h,"src",e.previewUrl),N(x,"href",e.previewUrl)}),z("click",u,d=>{d.target===d.currentTarget&&e.onClose()}),z("keydown",u,d=>{d.key==="Escape"&&e.onClose()}
1),z("click",E,function(...d){var f;(f=e.onClose)==null||f.apply(this,d)}),b(m,u),V()}re(["click","keydown"]);var Oe=C('<div class="bg-white rounded-2xl border border-stone-200 shadow-sm p-12 text-center"><div class="w-16 h-16 bg-green-50 rounded-2xl flex items-center justify-center mx-auto mb-4"><!></div> <h3 class="text-lg font-semibold text-stone-900 mb-2">No failed extractions</h3> <p class="text-stone-500"><!></p></div>'),Be=C('<div class="space-y-6"><div><h1 class="text-3xl font-bold text-stone-900">Failed Extractions</h1> <p class="text-stone-600 mt-1">Menu images that failed AI extraction during onboarding</p></div> <!> <!> <div class="space-y-4"><!></div> <!></div> <!> <!>',1);function ct(m,e){J(e,!0);let u=K(!1),v=K(null),h=K(!1),o=K(null);function x(l,y){A(o,{id:l,status:y},!0),A(h,!0)}async function g(){if(i(o)){A(u,!0);try{const l=await fetch("/api/v1/admin/failed-extractions",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:i(o).id,status:i(o).status})});if(l.ok)Z.add({message:`Extraction marked as ${i(o).status}`,type:"success",duration:4e3}),await xe();else{const y=await l.json();Z.add({message:y.error||"Failed to update status",type:"error",duration:6e3})}}catch{Z.add({message:"An unexpected error occurred",type:"error",duration:6e3})}finally{A(u,!1),A(o,null)}}}var E=Be();ve("164f8xa",l=>{ce(()=>{ue.title="Failed Extractions | FoodFlow Admin"})});var d=W(E),f=r(t(d),2);Ce(f,{get stats(){return e.data.stats}});var T=r(f,2);Fe(T,{get stats(){return e.data.stats},get currentFilter(){return e.data.currentFilter}});var _=r(T,2),s=t(_);{var w=l=>{var y=Oe(),j=t(y),p=t(j);de(p,{class:"w-8 h-8 text-green-500"}),a(j);var P=r(j,4),Y=t(P);{var q=L=>{var H=ee();I(()=>k(H,`No extractions match the "${e.data.currentFilter??""}" filter.`)),b(L,H)},X=L=>{var H=ee("All menu extractions have been processed successfully.");b(L,H)};D(Y,L=>{e.data.currentFilter?L(q):L(X,-1)})}a(P),a(y),b(l,y)},M=l=>{var y=ae(),j=W(y);ne(j,17,()=>e.data.extractions,ie,(p,P)=>{Ae(p,{get extraction(){return i(P)},get isLoading(){return i(u)},onPreview:Y=>A(v,Y,!0),onStatusChange:x})}),b(l,y)};D(s,l=>{e.data.extractions.length===0?l(w):l(M,-1)})}a(_);var O=r(_,2);{var G=l=>{Re(l,{get pagination(){return e.data.pagination},get currentFilter(){return e.data.currentFilter}})};D(O,l=>{e.data.pagination.totalPages>1&&l(G)})}a(d);var F=r(d,2);{var S=l=>{ze(l,{get previewUrl(){return i(v)},onClose:()=>A(v,null)})};D(F,l=>{i(v)&&l(S)})}var B=r(F,2);{let l=Q(()=>{var p,P;return((p=i(o))==null?void 0:p.status)==="processed"?"Mark this extraction as processed? This means you've manually built the menu for this restaurant.":((P=i(o))==null?void 0:P.status)==="failed"?"Mark this extraction as permanently failed? You can reopen it later if needed.":"Reopen this extraction and set it back to pending?"}),y=Q(()=>{var p,P;return((p=i(o))==null?void 0:p.status)==="processed"?"Mark Processed":((P=i(o))==null?void 0:P.status)==="failed"?"Mark Failed":"Reopen"}),j=Q(()=>{var p;return((p=i(o))==null?void 0:p.status)==="processed"?"success":"danger"});ge(B,{title:"Update Extraction Status",get message(){return i(l)},get confirmText(){return i(y)},cancelText:"Cancel",get variant(){return i(j)},onConfirm:g,onCancel:()=>{A(o,null)},get open(){return i(h)},set open(p){A(h,p,!0)}})}b(m,E),V()}export{ct as component};
2//# sourceMappingURL=19.c1ABkSMY.js.map

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.