PageSourceSearch

https://myechoboard.com/assets/AdminBulkUploadModal-Ka_ilUka.js

js myechoboard.com collected 2026-09-24 13:51:00 UTC 31,195 bytes, 1 lines download raw bytes

1import{r as e,j as t}from"./vendor-react-C9yDzYQD.js";import{supabase as a}from"./supabase-client-_h80EYw_.js";import{B as r}from"./button-CcIRk75H.js";import{T as o}from"./textarea-vEj0waFH.js";import{D as l,a as s,b as i,c as n,d}from"./dialog-DHNNRuDw.js";import{S as c,a as u,b as p,c as m,d as h}from"./select-BE1IGN5Z.js";import{T as f,a as g,b as x,c as w}from"./tabs-DdWd6h3i.js";import{S as v}from"./switch-CM-712rT.js";import{V as b}from"./VoidDropZone-3EAG2fTe.js";import{UploadQueue as y}from"./UploadQueue-DWC6nTL0.js";import{u as j}from"./useAuth-Dz3EPsxs.js";import{u as N}from"./useImageCompression-CcXi4sud.js";import{g as k,a as U}from"./videoUtils-CgPXwgg1.js";import{m as A,n as D}from"./image-utils-AdRSPECl.js";import{u as S,f as _,a as C}from"./r2-upload-BKh8xYPI.js";import{v as P,r as F}from"./clipboardPaste-CCCQEmTP.js";import{b as I}from"./runtime-utils-GN4cODRt.js";import{u as Q}from"./useDocumentVisibility-D-qOhV7W.js";import{C as $}from"./circle-check-DwjPV3g7.js";import{C as E}from"./clock-Qxd67VZh.js";import{C as L}from"./circle-x-tTPWE6xb.js";import{I as T}from"./image-Bt9rnFUc.js";import{P as R}from"./play-DCyyoljT.js";import{P as M}from"./pause-D8B9S2ve.js";import{P as z}from"./panels-top-left-CSwYcjk9.js";import{F as B}from"./folder-open-Bn7HwDJq.js";import{L as O}from"./loader-circle-CWK_zhHB.js";import{U as q}from"./upload-DddxHbzP.js";const V=e=>{if((null==e?void 0:e.startsWith("blob:"))&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL)try{URL.revokeObjectURL(e)}catch{}},J=I,W=async(e,t=3,a=1e3)=>{try{return await e()}catch(r){if(t<=0)throw r;const o=r instanceof Error?r.message:String(r);if(!(o.toLowerCase().includes("fetch")||o.toLowerCase().includes("network")||o.toLowerCase().includes("timeout")))throw r;return await new Promise(e=>setTimeout(e,a)),W(e,t-1,2*a)}},H=async(e,t)=>{const a=await fetch(e),r=await a.blob();return new File([r],t,{type:r.type||"image/jpeg"})},Z=e=>{const t=P(e);return t.ok?t.kind:null},G=(e,t)=>{if(e.type)return e.type;const a=(e=>{var t;return(null==(t=e.name.split(".").pop())?void 0:t.trim().toLowerCase())||""})(e);return"image"===t?"png"===a?"image/png":"webp"===a?"image/webp":"gif"===a?"image/gif":"avif"===a?"image/avif":"heic"===a||"heif"===a?"image/heic":"image/jpeg":"video"===t?F(e)||"video/mp4":"application/octet-stream"},K="jobs",Y=()=>new Promise((e,t)=>{const a=indexedDB.open("echo-admin-bulk",1);a.onupgradeneeded=()=>{const e=a.result;e.objectStoreNames.contains(K)||e.createObjectStore(K,{keyPath:"id"})},a.onsuccess=()=>e(a.result),a.onerror=()=>t(a.error)}),X=async e=>{const t=await Y();await new Promise((a,r)=>{const o=t.transaction(K,"readwrite");o.objectStore(K).put(e),o.oncomplete=()=>a(),o.onerror=()=>r(o.error)}),t.close()},ee=async e=>{const t=await Y();await new Promise((a,r)=>{const o=t.transaction(K,"readwrite");o.objectStore(K).delete(e),o.oncomplete=()=>a(),o.onerror=()=>r(o.error)}),t.close()};const te=e=>new Promise((t,a)=>e.file(t,a)),ae=async e=>{if(e.isFile)return[await te(e)];if(!e.isDirectory)return[];const t=await(a=e,new Promise((e,t)=>{const r=a.createReader(),o=[],l=()=>{r.readEntries(t=>{0!==t.length?(o.push(...t),l()):e(o)},t)};l()}));var a;return(await Promise.all(t.map(ae))).flat()};function re({user:P,onClose:F,onSuccess:I}){const te=Q(),[re,oe]=e.useState(""),[le,se]=e.useState(()=>P.boards_info||[]),[ie,ne]=e.useState(!1),[de,ce]=e.useState(""),[ue,pe]=e.useState(!1),[me,he]=e.useState({done:0,total:0}),[fe,ge]=e.useState(!1),{toast:xe}=j(),we=e.useRef(null),ve=e.useRef(null),[be,ye]=e.useState(!1),{uploadItems:je,stats:Ne,phase:ke,isPaused:Ue,setPaused:Ae,addMultipleToQueue:De,addFilesToQueue:Se,isProcessing:_e,clearCompleted:Ce,clearAll:Pe,removeFromQueue:Fe}=function(t,r,o=!1,l){const[s,i]=e.useState([]),[n,d]=e.useState({totalQueued:0,totalDone:0,totalFailed:0,totalActive:0}),[c,u]=e.useState("idle"),p=e.useRef(null),m=e.useRef(!1),h=e.useRef([]),f=e.useRef(new Set),g=e.useRef(!0);h.current=s,e.useEffect(()=>{const e=f,t=h;return g.current=!0,()=>{g.current=!1,e.current.forEach(clearTimeout),e.current.clear(),t.current.forEach(e
1=>V(e.previewUrl))}},[]);const x=e.useRef(!1),[w,v]=e.useState(!1),{toast:b}=j(),{compressImage:y}=N(),P=e.useCallback(async e=>{if(p.current)try{const a={id:p.current,targetUserId:t,targetBoardId:r,phase:e.phase||c,totalQueued:e.totalQueued??n.totalQueued,totalDone:e.totalDone??n.totalDone,totalFailed:e.totalFailed??n.totalFailed,pendingItems:e.pendingItems||[],createdAt:Date.now(),updatedAt:Date.now()};await X(a)}catch{}},[t,r,c,n.totalQueued,n.totalDone,n.totalFailed]),F=e.useCallback(async(e,o)=>{if(0===e.length)return;u("linking");let s=[...e];const i=[];for(let t=0;t<e.length;t+=100)i.push(e.slice(t,t+100));let n=0;const c=async e=>{const l=e.map(e=>({type:e.type,title:e.title,image_url:"image"===e.type?e.publicUrl:void 0,video_url:"video"===e.type?e.publicUrl:void 0,metadata:e.metadata}));try{const{data:s,error:i}=await W(()=>a.functions.invoke("admin-bulk-insert",{body:{target_user_id:t,target_board_id:r,items:l},headers:{Authorization:`Bearer ${o}`}}));if(i)throw i;if(!(null==s?void 0:s.success))throw new Error((null==s?void 0:s.error)||"Bulk insert failed");return Math.min(e.length,s.imported||0)}catch(s){if(e.length<=10)throw s;const t=Math.ceil(e.length/2),[a,r]=await Promise.all([c(e.slice(0,t)),c(e.slice(t))]);return a+r}};await Promise.all(Array.from({length:Math.min(2,i.length)},async()=>{for(;n<i.length;){for(;x.current;)await new Promise(e=>setTimeout(e,300));const t=n++;if(t>=i.length)break;const a=i[t];d(e=>({...e,totalActive:e.totalActive+1}));try{const e=await c(a),t=Math.max(0,a.length-e);if(t>0&&d(e=>({...e,totalDone:Math.max(0,e.totalDone-t),totalFailed:e.totalFailed+t})),e===a.length){const e=new Set(a.map(e=>e.publicUrl));s=s.filter(t=>!e.has(t.publicUrl))}await P({phase:"linking",pendingItems:s}),null==l||l(null)}catch(e){d(e=>({...e,totalDone:Math.max(0,e.totalDone-a.length),totalFailed:e.totalFailed+a.length})),await P({phase:"linking",pendingItems:s})}finally{d(e=>({...e,totalActive:Math.max(0,e.totalActive-1)}))}}})),0===s.length?(u("done"),p.current&&(await ee(p.current).catch(()=>{}),p.current=null)):(u("linking"),await P({phase:"linking",pendingItems:s}),b({title:"Upload paused with pending links",description:`${s.length.toLocaleString()} items will resume on reload/open.`,variant:"error"}))},[l,P,r,t,b]),I=e.useCallback(e=>{x.current=e,v(e)},[]),Q=e.useCallback((e,t)=>{g.current?i(a=>a.map(a=>a.id!==e?a:("string"==typeof t.previewUrl&&a.previewUrl&&a.previewUrl!==t.previewUrl&&V(a.previewUrl),{...a,...t}))):V(t.previewUrl)},[]),$=e.useCallback(e=>{const t=setTimeout(()=>{f.current.delete(t),i(t=>(t.forEach(t=>{t.id===e&&V(t.previewUrl)}),t.filter(t=>t.id!==e)))},3e3);f.current.add(t)},[]),E=e.useCallback(async(e,s)=>{var i,n,c,u;try{for(;x.current;)await new Promise(e=>setTimeout(e,300));const{data:{session:h}}=await a.auth.getSession(),f={...s,target_user_id:t,target_board_id:r,skip_ai_analysis:!o,client_request_id:s.client_request_id||e.id};let g=null,w=null;if(Q(e.id,{status:"uploading",progress:10}),d(e=>({...e,totalActive:e.totalActive+1})),f.file)if("image"===f.type){const t="image/gif"===(u=f.file).type||u.name.toLowerCase().endsWith(".gif"),a=t?f.file:await y(f.file);e.previewUrl||Q(e.id,{previewUrl:URL.createObjectURL(a)});const r=await new Promise(e=>{const t=new FileReader;t.onload=t=>{var a,r;return e(null==(r=null==(a=t.target)?void 0:a.result)?void 0:r.split(",")[1])},t.readAsDataURL(a)});f.imageBase64=r,f.imageMimeType=a.type||f.file.type||"image/jpeg";const o=await A(a).catch(()=>null);o&&(f.metadata={...f.metadata,mime_type:a.type||f.file.type||"image/jpeg",is_animated:t,width:o.width,height:o.height,aspect_ratio:o.width/o.height}),Q(e.id,{progress:30})}else if("video"===f.type){const a=f.file.name.split(".").pop()||"mp4",r=`${t}/${Date.now()}-${J()}`;g=`${r}.${a}`,w=`${r}_thumbnail.jpg`;try{const t=await k(f.file);if(Q(e.id,{previewUrl:t}),null==h?void 0:h.user){const e=await H(t,"video-thumbnail.jpg"),[a,o]=await Promise.all([S(e,h.access_token,w||`${r}_thumbnail.jpg`,e.type),D(e).catch(()=>"#171717")]);f.metadata={...f.metadata,thumbnail_url:a,dominant_color:o}}}catch(p){}const o=await U(f.file).catch(()=>null);o&&(f.metadata={...f.metadata,width:o.width,height:o.height,aspect_ratio:o.width/o.height})}if("video"===f.type&&f.file&&(null==h?void 0:h.user)){Q(e.id,{status:"uploading",progress:40});const r=g||`${t}/${Date.now()}-${J()}.mp4`,o=f.videoMimeType||f.file.type||"video/mp4",{data:l,error:s}=await W(()=>a.functions.invoke("upload-to-r2",{body:{action:"get-upload-url",fileName:r,contentType:o,fileSize:f.file.size},headers:{Authorization:`Bearer ${h.access_token}`}}));if(s||!(null==l?void 0:l.uploadUrl)||!(null==l?void 0:l.uploadId))throw new Error("Failed to get upload URL");try{if(!(await fetch(l.uploadUrl,{method:"PUT",body:f.file,headers:{"Content-Type":o}})).ok)throw new Error("R2 upload failed");await _(l.uploadId,r,h.access_token)}catch(m){throw await C(l.uploadId,h.access_token),m}f.videoUrl=l.publicUrl,delete f.file,Q(e.id,{progress:60})}if(Q(e.id,{status:"processing",progress:80}),("image"===f.type||"video"===f.type)&&!(null==(i=f.metadata)?void 0:i.orientation)&&e.previewUrl){const t=await(n=f.type,c=e.previewUrl,
1new Promise(e=>{if("image"===n){const t=new Image;t.onload=()=>{const a=t.width>t.height?"landscape":t.width<t.height?"portrait":"square";t.onload=null,t.onerror=null,t.src="",e(a)},t.onerror=()=>{t.onload=null,t.onerror=null,t.src="",e("")},t.src=c}else if("video"===n){const t=document.createElement("video"),a=()=>{t.onloadedmetadata=null,t.onerror=null,t.removeAttribute("src"),t.load()};t.onloadedmetadata=()=>{const r=t.videoWidth>t.videoHeight?"landscape":t.videoWidth<t.videoHeight?"portrait":"square";a(),e(r)},t.onerror=()=>{a(),e("")},t.src=c}}));t&&(f.metadata={...f.metadata,orientation:t})}const v=(await W(async()=>{var e,t,r,o,l;const s=await a.functions.invoke("process-memory",{body:f,headers:h?{Authorization:`Bearer ${h.access_token}`}:{}});if(s.error||!0!==(null==(e=s.data)?void 0:e.success)||!(null==(t=s.data)?void 0:t.memory))throw new Error(`${(null==(r=s.data)?void 0:r.code)?`${s.data.code}: `:""}${(null==(o=s.error)?void 0:o.message)||(null==(l=s.data)?void 0:l.error)||"Failed to process"}`);return s})).data;if((null==v?void 0:v.success)&&(null==v?void 0:v.memory))return Q(e.id,{status:"complete",progress:100}),d(e=>({...e,totalDone:e.totalDone+1,totalActive:Math.max(0,e.totalActive-1)})),$(e.id),null==l||l(v.memory),v.memory;throw new Error((null==v?void 0:v.error)||"Failed to process")}catch(m){return Q(e.id,{status:"error",error:m.message}),d(e=>({...e,totalFailed:e.totalFailed+1,totalActive:Math.max(0,e.totalActive-1)})),$(e.id),null}},[Q,$,l,y,t,r,o]),L=e.useCallback(async(e,t)=>{i(t=>{const a=[...t,...e],r=a.slice(-80),o=new Set(r.map(e=>e.id));return a.forEach(e=>{o.has(e.id)||V(e.previewUrl)}),r});let a=0;const r=Array.from({length:Math.min(8,e.length)},async()=>{for(;a<e.length;){const r=a++;if(r>=e.length)break;await E(e[r],t[r])}});await Promise.all(r)},[E]),T=e.useCallback(async e=>{const t=e.filter(e=>!(!e||!e.input)||(V(null==e?void 0:e.previewUrl),!1)),a=t.map(e=>{var t;return{id:J(),type:e.input.type,name:e.input.title||(null==(t=e.input.file)?void 0:t.name)||"Upload",status:"pending",progress:0,previewUrl:e.previewUrl}}),r=t.map(e=>e.input);u("uploading"),d(e=>({...e,totalQueued:e.totalQueued+a.length})),await L(a,r),u("done")},[L]),R=e.useCallback(async e=>{const l=e.filter(e=>Z(e));if(0===l.length)return void b({title:"No supported files",description:"Please select images or videos.",variant:"error"});const s=e.length-l.length;s>0&&b({title:`Skipped ${s} unsupported file(s)`,description:"Only images and videos are supported."});const i=`${t}:${r}:${Date.now()}`;if(p.current=i,u("uploading"),d(e=>({...e,totalQueued:e.totalQueued+l.length})),await X({id:i,targetUserId:t,targetBoardId:r,phase:"uploading",totalQueued:l.length,totalDone:0,totalFailed:0,pendingItems:[],createdAt:Date.now(),updatedAt:Date.now()}).catch(()=>{}),o){const e=l.map(e=>({id:J(),type:Z(e)||"image",name:e.name,status:"pending",progress:0})),t=l.map((t,a)=>({type:e[a].type,content:"",title:t.name,file:t}));return await L(e,t),void u("done")}const c=[];let m=0,h=0;const{data:{session:f}}=await a.auth.getSession(),g=(null==f?void 0:f.access_token)||"";return g?(await Promise.all(Array.from({length:Math.min(32,l.length)},async()=>{for(;m<l.length;){for(;x.current;)await new Promise(e=>setTimeout(e,300));const o=m++;if(o>=l.length)break;const s=l[o],i=Z(s);if(i){d(e=>({...e,totalActive:e.totalActive+1}));try{let r=s;const o=G(s,i),l={mime_type:o,original_filename:s.name};if("image"===i){r=await y(s);const e=await A(r).catch(()=>null);e&&(l.width=e.width,l.height=e.height,l.aspect_ratio=e.width/e.height,l.orientation=e.width>e.height?"landscape":e.width<e.height?"portrait":"square")}else if("video"===i){const e=await U(s).catch(()=>null);e&&(l.width=e.width,l.height=e.height,l.aspect_ratio=e.width/e.height,l.orientation=e.width>e.height?"landscape":e.width<e.height?"portrait":"square")}const u=s.name.split(".").pop()||("image"===i?"jpg":"mp4"),p=`${t}/${Date.now()}-${J()}.${u}`,m="video"===i?p.replace(/\.[^/.]+$/,"_thumbnail.jpg"):null,{data:f,error:x}=await W(()=>a.functions.invoke("upload-to-r2",{body:{action:"get-upload-url",fileName:p,contentType:o,fileSize:r.size}}));if(x||!(null==f?void 0:f.uploadUrl)||!(null==f?void 0:f.uploadId))throw new Error("Failed to get upload URL");try{const e=await fetch(f.uploadUrl,{method:"PUT",body:r,headers:{"Content-Type":o}});if(!e.ok)throw new Error(`R2 PUT failed: ${e.status}`);await _(f.uploadId,p,g)}catch(e){throw await C(f.uploadId,g),e}if("video"===i&&m)try{const e=await k(s),t=await H(e,"video-thumbnail.jpg"),[a,r]=await Promise.all([S(t,g,m,t.type),D(t).catch(()=>"#171717")]);l.thumbnail_url=a,l.dominant_color=r}catch(e){}c.push({publicUrl:f.publicUrl,type:i,title:s.name.replace(/\.[^/.]+$/,""),metadata:l}),d(e=>({...e,totalDone:e.totalDone+1,totalActive:Math.max(0,e.totalActive-1)})),h++,h%25==0&&await P({phase:"uploading",totalDone:c.length,totalFailed:n.totalFailed})}catch(r){d(e=>({...e,totalFailed:e.totalFailed+1,totalActive:Math.max(0,e.totalActive-1)}))}}}})),0===c.length?(b({title:"All uploads failed",description:"Could not upload any files to storage.",variant:"error"}),u("done"),void(p.current&&(await ee(p.current).catch(()=>{}),p.current=null))):(await P({phase:"linking",totalDone:c.length,pendingItems:c}),void(await F(c,g)))):(u("done"),p.current&&(await ee(p.current).catch(()=>{}),p.current=null),void b({title:"Not authenticated",description:"Please sign in again and retry.",variant:"error"}))},[L,y,t,r,o,b,F,P,n.totalFailed]),M=e.useCallback((e,t)=>{var a;const r=J(),o={id:r,type:e.type,name:e.title||(null==(a=e.file)?void 0:a.name)||"Upload",status:"pending",progress:0,previewUrl:t};return i(e=>[...e,o]),d(e=>({...e,totalQueued:e.totalQueued+1})),E(o,e),r},[E]),z=e.useCallback(()=>{i(e=>
1(e.forEach(e=>V(e.previewUrl)),[])),d({totalQueued:0,totalDone:0,totalFailed:0,totalActive:0}),u("idle"),p.current&&(ee(p.current).catch(()=>{}),p.current=null)},[]);return e.useEffect(()=>{t&&r&&(m.current||(m.current=!0,(async()=>{const e=await(async(e,t)=>{const a=await Y(),r=await new Promise((e,t)=>{const r=a.transaction(K,"readonly").objectStore(K).getAll();r.onsuccess=()=>e(r.result||[]),r.onerror=()=>t(r.error)});return a.close(),r.filter(a=>a.targetUserId===e&&a.targetBoardId===t&&"linking"===a.phase&&Array.isArray(a.pendingItems)&&a.pendingItems.length>0).sort((e,t)=>t.updatedAt-e.updatedAt)[0]||null})(t,r).catch(()=>null);if(!e||0===e.pendingItems.length)return;const{data:{session:o}}=await a.auth.getSession();(null==o?void 0:o.access_token)&&(p.current=e.id,u("linking"),d({totalQueued:e.totalQueued,totalDone:e.totalDone,totalFailed:e.totalFailed,totalActive:0}),b({title:"Resuming previous upload",description:`${e.pendingItems.length.toLocaleString()} items still linking.`}),await F(e.pendingItems,o.access_token))})()))},[t,r,b,F]),{uploadItems:s,stats:n,phase:c,isPaused:w,setPaused:I,addToQueue:M,addMultipleToQueue:T,addFilesToQueue:R,removeFromQueue:e=>i(t=>(t.forEach(t=>{t.id===e&&V(t.previewUrl)}),t.filter(t=>t.id!==e))),clearCompleted:()=>i(e=>(e.forEach(e=>{"complete"===e.status&&V(e.previewUrl)}),e.filter(e=>"complete"!==e.status))),clearAll:z,isProcessing:n.totalActive>0||s.some(e=>["pending","uploading","processing"].includes(e.status))}}(P.id,re,fe);e.useEffect(()=>{let e=!1;return(async()=>{if(null==P?void 0:P.id){ne(!0);try{const{data:t,error:r}=await a.rpc("admin_get_user_boards",{p_user_id:P.id});if(r)throw r;e||se(Array.isArray(t)?t:[])}catch(t){e||xe({title:"Failed to load user boards",description:t.message||"The target board list could not be loaded.",variant:"error"})}finally{e||ne(!1)}}})(),()=>{e=!0}},[xe,null==P?void 0:P.id]);const Ie=le.find(e=>e.id===re),Qe=!1===(null==Ie?void 0:Ie.is_public),$e=Ne.totalQueued>50,Ee=Ne.totalDone+Ne.totalFailed,Le=Math.max(0,Ne.totalQueued-Ee),Te=Ne.totalQueued>0?Math.round(Ee/Ne.totalQueued*100):0,Re=Ne.totalQueued>0&&"done"===ke&&0===Ne.totalActive&&Ee>=Ne.totalQueued,Me=ue||Ne.totalQueued>0&&!Re,[ze,Be]=e.useState(null),[Oe,qe]=e.useState(Date.now()),Ve=e.useRef(!1);e.useEffect(()=>{Ne.totalQueued>0&&null===ze&&Be(Date.now()),0===Ne.totalQueued&&null!==ze&&Be(null)},[Ne.totalQueued,ze]),e.useEffect(()=>{if(0===Ne.totalQueued||Re||!te)return;const e=window.setInterval(()=>qe(Date.now()),1e3);return()=>window.clearInterval(e)},[te,Ne.totalQueued,Re]),e.useEffect(()=>{Me&&(Ve.current=!1)},[Me]),e.useEffect(()=>{0!==Ne.totalQueued?Re&&!Ve.current&&(Ve.current=!0,I()):Ve.current=!1},[Re,I,Ne.totalQueued]),e.useEffect(()=>{if(!Me)return;const e=e=>{e.preventDefault(),e.returnValue=""};return window.addEventListener("beforeunload",e),()=>window.removeEventListener("beforeunload",e)},[Me]);const Je=ze?Math.max(1,Math.floor((Oe-ze)/1e3)):0,We=Je>=5?Ne.totalDone/Je*60:0,He=We>0&&Le>0?Le/We:null,Ze="uploading"===ke?"Uploading to storage":"linking"===ke?"Linking echoes to board":"done"===ke?"Completed":"Ready",Ge=e.useCallback(e=>{e&&0!==e.length&&(re?Se(Array.from(e)):xe({title:"Select a board first",variant:"error"}))},[Se,re,xe]),Ke=e.useCallback(async e=>{if(e.preventDefault(),ye(!1),re)try{const t=await(async e=>{var t;const a=[];for(const r of Array.from(e.items||[])){const e=r,o=null==(t=e.webkitGetAsEntry)?void 0:t.call(e);o&&a.push(o)}return 0===a.length?Array.from(e.files||[]):(await Promise.all(a.map(ae))).flat()})(e.dataTransfer);t.length>0&&Se(t)}catch(t){xe({title:"Could not read dropped folders",description:(null==t?void 0:t.message)||"Try selecting the folder instead.",variant:"error"})}else xe({title:"Select a board first",variant:"error"})},[Se,re,xe]);return t.jsx(l,{open:!0,onOpenChange:e=>{e||Me||F()},children:t.jsxs(s,{className:"sm:max-w-[680px] md:max-w-[760px] max-h-[92vh] flex flex-col border-foreground
1/10 bg-background/95 backdrop-blur-xl overflow-hidden p-0 rounded-[2rem] shadow-2xl",onEscapeKeyDown:e=>{Me&&e.preventDefault()},onInteractOutside:e=>{Me&&e.preventDefault()},onPointerDownOutside:e=>{Me&&e.preventDefault()},children:[t.jsxs(i,{className:"p-6 pb-3 shrink-0",children:[t.jsxs(n,{className:"text-lg",children:["Mass Upload → ",P.full_name||P.email]}),t.jsx(d,{children:"Import thousands of local files to this user's board. 32 parallel uploads + batched DB linking for maximum speed."})]}),t.jsxs("div",{className:"flex-1 overflow-y-auto px-6 pb-4 space-y-5 custom-scrollbar",children:[t.jsxs("div",{className:"flex gap-3 items-center",children:[t.jsxs("div",{className:"flex-1 space-y-1.5",children:[t.jsx("label",{className:"text-[10px] font-bold text-muted-foreground uppercase tracking-widest ml-1",children:"Target Board"}),t.jsxs(c,{value:re,onValueChange:oe,children:[t.jsx(u,{className:"rounded-2xl bg-muted/20 border-none h-11 shadow-inner",disabled:ie,children:t.jsx(p,{placeholder:ie?"Loading boards...":"Select a board..."})}
1),t.jsx(m,{className:"rounded-2xl border-foreground/10 shadow-2xl",children:le.map(e=>t.jsxs(h,{value:e.id,className:"rounded-lg",children:[e.name," ",e.is_public?"(Public)":"(Private)"]},e.id))})]}),!ie&&0===le.length&&t.jsx("p",{className:"text-[10px] font-semibold text-amber-500 ml-1",children:"No boards found for this user."}),Ie&&Qe&&t.jsx("p",{className:"text-[10px] font-semibold text-amber-500 ml-1",children:"This board is private. This only affects the public profile page; Admin Users counts still include all account echoes."})]}),t.jsxs("div",{className:"shrink-0 flex items-center gap-3 p-3 bg-primary/5 rounded-2xl border border-primary/10 mt-6",children:[t.jsxs("div",{children:[t.jsx("p",{className:"text-[10px] font-bold text-foreground leading-none",children:"Smart AI"}),t.jsx("p",{className:"text-[9px] text-muted-foreground mt-0.5",children:"Slower"})]}),t.jsx(v,{checked:fe,onCheckedChange:ge})]})]}),Ne.totalQueued>0&&t.jsxs("div",{className:"rounded-2xl border border-foreground/10 bg-foreground/[0.02] p-4 space-y-3",children:[t.jsx("div",{className:"w-full bg-muted/40 rounded-full h-2 overflow-hidden",children:t.jsx("div",{className:"h-full bg-primary rounded-full transition-all duration-500",style:{width:`${Te}%`}})}),t.jsxs("div",{className:"flex items-center justify-between",children:[t.jsxs("div",{className:"flex items-center gap-4 text-[11px]",children:[t.jsxs("span",{className:"flex items-center gap-1.5 text-emerald-500 font-semibold",children:[t.jsx($,{className:"w-3.5 h-3.5"}),Ne.totalDone.toLocaleString()," done"]}),t.jsxs("span",{className:"flex items-center gap-1.5 text-primary font-semibold",children:[t.jsx(E,{className:"w-3.5 h-3.5"}),Ne.totalActive," active"]}),Ne.totalFailed>0&&t.jsxs("span",{className:"flex items-center gap-1.5 text-destructive font-semibold",children:[t.jsx(L,{className:"w-3.5 h-3.5"}),Ne.totalFailed," failed"]}),t.jsxs("span",{className:"flex items-center gap-1.5 text-muted-foreground font-semibold",children:[t.jsx(T,{className:"w-3.5 h-3.5"}),Ne.totalQueued.toLocaleString()," total"]})]}),t.jsx("div",{className:"flex items-center gap-2",children:Re?t.jsx(r,{size:"sm",variant:"ghost",onClick:Pe,className:"h-7 text-[10px] font-bold uppercase tracking-widest rounded-lg",children:"Clear All"}):t.jsx(r,{size:"sm",variant:"ghost",onClick:()=>Ae(!Ue),className:"h-7 text-[10px] font-bold uppercase tracking-widest rounded-lg gap-1.5",children:Ue?t.jsxs(t.Fragment,{children:[t.jsx(R,{className:"w-3 h-3"})," Resume"]}):t.jsxs(t.Fragment,{children:[t.jsx(M,{className:"w-3 h-3"})," Pause"]})})})]}),!Re&&t.jsxs("div",{className:"flex items-center justify-between text-[10px] text-muted-foreground font-semibold",children:[t.jsx("span",{children:Ze}),t.jsxs("span",{children:[Le.toLocaleString()," remaining"]}),t.jsx("span",{children:We>0?`${Math.round(We).toLocaleString()}/min`:"estimating…"}),t.jsx("span",{children:null!==He?"ETA "+(Ye=He,Ye<1?"<1m":Ye<60?`${Math.ceil(Ye)}m`:`${Math.floor(Ye/60)}h ${Math.ceil(Ye%60)}m`):"ETA —"})]}),Re&&t.jsxs("p",{className:"text-[11px] text-emerald-500 font-bold text-center",children:["All done! ",Ne.totalDone.toLocaleString()," echoes uploaded.",Ne.totalFailed>0&&` ${Ne.totalFailed} failed.`]}),Ue&&!Re&&t.jsx("p",{className:"text-[11px] text-amber-500 font-bold text-center animate-pulse",children:"Paused — workers will finish current item then wait."})]}),t.jsxs(f,{defaultValue:"folder",className:"w-full",children:[t.jsxs(g,{className:"grid w-full grid-cols-3 p-1.5 bg-muted/30 rounded-2xl mb-5",children:[t.jsx(x,{value:"folder",className:"rounded-xl font-bold text-xs py-2 data-[state=active]:bg-background data-[state=active]:shadow-sm",children:"Folder / Files"}),t.jsx(x,{value:"desktop",className:"rounded-xl font-bold text-xs py-2 data-[state=active]:bg-background data-[state=active]:shadow-sm",children:"Drop Zone"}),t.jsx(x,{value:"json",className:"rounded-xl font-bold text-xs py-2 data-[state=active]:bg-background data-[state=active]:shadow-sm",children:"JSON Import"})]}),t.jsx(w,{value:"folder",className:"mt-0 space-y-3",children:re?t.jsxs(t.Fragment,{children:[t.jsxs("div",{onDragOver:e=>{e.preventDefault(),ye(!0)},onDragLeave:()=>ye(!1),onDrop:Ke,className:"relative flex flex-col items-center justify-center gap-4 p-10 rounded-3xl border-2 border-dashed transition-colors cursor-pointer\n                                            "+(be?"border-primary bg-primary/5":"border-foreground
1/10 bg-foreground/[0.02] hover:border-foreground/20 hover:bg-foreground/[0.04]"),onClick:()=>{var e;return null==(e=ve.current)?void 0:e.click()},children:[t.jsx(B,{className:"w-10 h-10 transition-colors "+(be?"text-primary":"opacity-20")}),t.jsxs("div",{className:"text-center",children:[t.jsx("p",{className:"text-sm font-bold text-foreground",children:"Drag files or folders here"}),t.jsx("p",{className:"text-[11px] text-muted-foreground mt-1",children:"Drop multiple folders at once, or add folders one by one"})]}),t.jsxs("div",{className:"flex gap-2",children:[t.jsxs(r,{type:"button",size:"sm",variant:"outline",className:"rounded-xl h-9 text-xs font-bold gap-2",onClick:e=>{var t;e.stopPropagation(),null==(t=ve.current)||t.click()},children:[t.jsx(T,{className:"w-3.5 h-3.5"})," Select Files"]}),t.jsxs(r,{type:"button",size:"sm",variant:"outline",className:"rounded-xl h-9 text-xs font-bold gap-2",onClick:e=>{var t;e.stopPropagation(),null==(t=we.current)||t.click()},children:[t.jsx(B,{className:"w-3.5 h-3.5"})," Add Folder"]})]}),t.jsx("input",{ref:ve,type:"file",multiple:!0,accept:"image/*,video/*",className:"hidden",onChange:e=>{Ge(e.target.files),e.currentTarget.value=""}}),t.jsx("input",{ref:we,type:"file",webkitdirectory:"",directory:"",multiple:!0,className:"hidden",onChange:e=>{Ge(e.target.files),e.currentTarget.value=""}})]}),je.length>
10&&!$e&&t.jsxs("div",{className:"bg-foreground/[0.02] rounded-3xl border border-foreground/10 overflow-hidden shadow-inner",children:[t.jsxs("div",{className:"p-4 border-b border-foreground/5 flex items-center justify-between",children:[t.jsx("h4",{className:"text-[10px] font-bold uppercase tracking-widest text-muted-foreground ml-1",children:"Upload Queue"}),t.jsx(r,{size:"sm",variant:"ghost",onClick:Ce,className:"h-7 text-[10px] font-bold uppercase tracking-widest rounded-lg",children:"Clear Done"})]}),t.jsx("div",{className:"max-h-[200px] overflow-y-auto",children:t.jsx(y,{items:je,onRemove:Fe,onDismissCompleted:Ce,className:"static w-full max-h-none shadow-none border-none p-0 m-0 backdrop-blur-none bg-transparent"})})]}),$e&&t.jsx("p",{className:"text-center text-[10px] text-muted-foreground",children:"Individual item list hidden for performance — use the progress bar above."})]}):t.jsxs("div",{className:"p-10 text-center rounded-3xl border-2 border-dashed border-foreground/5 bg-foreground/[0.02]",children:[t.jsx(z,{className:"w-10 h-10 mx-auto mb-4 opacity-10"}),t.jsx("p",{className:"text-[11px] font-bold text-muted-foreground uppercase tracking-wider",children:"Select a board first"})]})}),t.jsx(w,{value:"desktop",className:"mt-0 space-y-4",children:re?t.jsxs("div",{className:"space-y-4",children:[t.jsx(b,{onDrop:e=>De([{input:e}]),onDropMultiple:e=>De(e),isProcessing:_e}),je.length>
10&&!$e&&t.jsxs("div",{className:"bg-foreground/[0.02] rounded-3xl border border-foreground/10 overflow-hidden shadow-inner",children:[t.jsxs("div",{className:"p-4 border-b border-foreground/5 flex items-center justify-between",children:[t.jsx("h4",{className:"text-[10px] font-bold uppercase tracking-widest text-muted-foreground ml-1",children:"Upload Queue"}),t.jsx(r,{size:"sm",variant:"ghost",onClick:Ce,className:"h-7 text-[10px] font-bold uppercase tracking-widest rounded-lg",children:"Clear Done"})]}),t.jsx("div",{className:"max-h-[200px] overflow-y-auto",children:t.jsx(y,{items:je,onRemove:Fe,onDismissCompleted:Ce,className:"static w-full max-h-none shadow-none border-none p-0 m-0 backdrop-blur-none bg-transparent"})})]})]}):t.jsxs("div",{className:"p-10 text-center rounded-3xl border-2 border-dashed border-foreground/5 bg-foreground/[0.02]",children:[t.jsx(z,{className:"w-10 h-10 mx-auto mb-4 opacity-10"}),t.jsx("p",{className:"text-[11px] font-bold text-muted-foreground uppercase tracking-wider",children:"Select a board first"})]})}),t.jsxs(w,{value:"json",className:"mt-0 space-y-4",children:[t.jsxs("div",{className:"space-y-2",children:[t.jsx("label",{className:"text-[10px] font-bold text-muted-foreground uppercase tracking-widest ml-1",children:"JSON Input (Array of pins)"}),t.jsx(o,{placeholder:'[{"imageUrl": "...", "videoUrl": "...", "link": "...", "description": "..."}]',className:"h-[180px] font-mono text-[11px] bg-muted/20 border-none rounded-3xl p-5 resize-none shadow-inner",value:de,onChange:e=>ce(e.target.value)})]}),ue&&me.total>0&&t.jsxs("div",{className:"space-y-2",children:[t.jsx("div",{className:"w-full bg-muted/40 rounded-full h-2 overflow-hidden",children:t.jsx("div",{className:"h-full bg-primary rounded-full transition-all duration-300",style:{width:`${Math.round(me.done/me.total*100)}%`}})}),t.jsxs("p",{className:"text-[11px] text-center text-muted-foreground font-semibold",children:[me.done.toLocaleString()," / ",me.total.toLocaleString()," imported…"]})]}),t.jsxs(r,{onClick:async()=>{if(!re)return void xe({title:"Please select a board",variant:"error"});let e=[];try{if(e=JSON.parse(de),!Array.isArray(e))throw new Error("Input must be a JSON array")}catch(s){return void xe({title:"Invalid JSON",description:s.message,variant:"error"})}const t=500,r=[];for(let a=0;a<e.length;a+=t)r.push(e.slice(a,a+t));pe(!0),he({done:0,total:e.length});let o=0,l=0;try{for(let s=0;s<r.length;s+=4){const i=r.slice(s,s+4),n=await Promise.allSettled(i.map(e=>a.rpc("admin_bulk_import",{p_user_id:P.id,p_board_id:re,p_items:e})));for(const e of n)if("fulfilled"===e.status){const{data:a,error:r}=e.value;r?l+=t:o+=a&&"object"==typeof a&&!Array.isArray(a)&&"imported"in a&&Number(a.imported)||0}else l+=t;he({done:o,total:e.length})}if(!(o>0))throw new Error("No items were imported successfully.");xe({title:"Import complete",description:`Imported ${o} echoes for ${P.full_name||P.email}.${l>0?` ${l} failed.`:""}`}),I()}catch(i){xe({title:"Import failed",description:i.message,variant:"error"})}finally{pe(!1),he({done:0,total:0})}},disabled:ue||!de||!re,className:"w-full h-14 rounded-3xl bg-primary hover:bg-primary/90 text-white font-bold gap-3 shadow-lg shadow-primary/20 transition-all active:scale-[0.98]",children:[ue?t.jsx(O,{className:"w-5 h-5 animate-spin"}):t.jsx(q,{className:"w-5 h-5"}),ue?"Importing…":"Start Bulk Upload"]})]})]})]}
1),t.jsxs("div",{className:"p-4 pt-0 border-t border-foreground/5 bg-muted/5 flex justify-between items-center shrink-0",children:[t.jsx("p",{className:"text-[10px] text-muted-foreground ml-1",children:_e?`${Ne.totalActive} uploading…`:Ne.totalQueued>0?`${Ne.totalQueued.toLocaleString()} files queued`:"Ready"}),t.jsx(r,{variant:"ghost",onClick:F,disabled:ue,className:"rounded-xl h-12 px-6 font-bold",children:_e?"Close (runs in background)":"Close"})]})]})});var Ye}export{re as AdminBulkUploadModal};

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.