PageSourceSearch

https://fyra.life/assets/IntakeAppleContacts-B-PSu_om.js

js fyra.life collected 2026-10-02 02:01:16 UTC 7,127 bytes, 2 lines download raw bytes

1import{u as P,r as d,j as e,B as g,T as N,s as F}from"./index-CEISlULX.js";import{P as R}from"./progress-DpNZy0Ke.js";import{A as V}from"./arrow-left-Dt5WA4Nk.js";import{U as M}from"./upload-C39KYR9i.js";import{L as A}from"./loader-circle-C0qiwHXp.js";import{U as I}from"./users-BDheGP7O.js";import{R as W}from"./refresh-cw-uC6mqHyu.js";import{F as D}from"./file-text-CamhJ3w8.js";const B=l=>{var j,u;const p=[],m=l.split("END:VCARD").filter(n=>n.includes("BEGIN:VCARD"));for(const n of m){const h=n.split(`
2`).map(s=>s.trim()),t={uid:"",displayName:"",emails:[],phones:[]};for(const s of h)if(s.startsWith("UID:"))t.uid=s.substring(4);else if(s.startsWith("FN:"))t.displayName=s.substring(3);else if(s.startsWith("N:")||s.startsWith("N;")){const i=s.match(/N[;:].*?:(.+)/);if(i){const o=i[1].split(";");t.lastName=o[0]||void 0,t.firstName=o[1]||void 0,!t.displayName&&(t.firstName||t.lastName)&&(t.displayName=[t.firstName,t.lastName].filter(Boolean).join(" "))}}else if(s.startsWith("EMAIL")){const i=s.match(/EMAIL[^:]*:(.+)/);if(i){const o=i[1].trim(),a=s.match(/TYPE=([^;:]+)/i);(j=t.emails)==null||j.push({value:o,type:a==null?void 0:a[1]}),t.email||(t.email=o)}}else if(s.startsWith("TEL")){const i=s.match(/TEL[^:]*:(.+)/);if(i){const o=i[1].trim().replace(/[^\d+\-() ]/g,""),a=s.match(/TYPE=([^;:]+)/i);(u=t.phones)==null||u.push({value:o,type:a==null?void 0:a[1]}),t.phone||(t.phone=o)}}t.uid||(t.uid=`vcf-${Date.now()}-${Math.random().toString(36).substring(7)}`),t.displayName&&p.push(t)}return p},K=()=>{const l=P(),[p,m]=d.useState(!1),[j,u]=d.useState(!1),[n,h]=d.useState(null),[t,s]=d.useState(0),[i,o]=d.useState(0),[a,c]=d.use
2State("idle"),U=async L=>{var y;const x=(y=L.target.files)==null?void 0:y[0];if(x){if(!x.name.endsWith(".vcf")){N({title:"Invalid file type",description:"Please upload a VCF file (.vcf)",variant:"destructive"});return}m(!0),h(x.name),c("parsing");try{const f=await x.text(),v=B(f);if(v.length===0){N({title:"No contacts found",description:"The VCF file appears to be empty or invalid",variant:"destructive"}),c("idle"),m(!1);return}s(v.length),c("saving"),u(!0);const{data:{user:C}}=await F.auth.getUser();if(!C)throw new Error("Not authenticated");const w=v.map(r=>({user_id:C.id,display_name:r.displayName||r.email||"Unknown",first_name:r.firstName||null,last_name:r.lastName||null,email:r.email||null,phone_e164:r.phone||null,avatar_url:null,source:"apple",external_id:r.uid,emails:r.emails||[],phones:r.phones||[]})),E=50;let b=0;for(let r=0;r<w.length;r+=E){const S=w.slice(r,r+E),{error:k}=await F.from("imported_contacts").upsert(S,{onConflict:"user_id,source,external_id",ignoreDuplicates:!1});if(k)throw k;b+=S.length,o(b)}c("done"),N({title:"Contacts imported!",description:`${b} contacts added to your address book.`}),setTimeout(()=>l("/contacts?tab=imported"),1500)}catch(f){console.error("Error importing contacts:",f),c("error"),N({title:"Failed to import contacts",description:f.message,variant:"destructive"})}finally{m(!1),u(!1)}}},T=()=>{h(null),s(0),o(0),c("idle")},_=t>0?Math.round(i/t*100):0;return e.jsxs("div",{className:"min-h-screen bg-background",children:[e.jsx("div",{className:"sticky top-0 z-10 bg-background border-b border-border",children:e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2",children:[e.jsx(g,{variant:"ghost",size:"icon",onClick:()=>l(-1),children:e.jsx(V,{className:"h-6 w-6"})}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-lg font-semibold",children:"Import Apple Contacts"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Upload your VCF file to import all contacts"})]})]})}),e.jsxs("div",{className:"p-4 flex flex-col items-center justify-center min-h-[60vh]",children:[a==="idle"&&e.jsxs("div",{className:"space-y-6 w-full max-w-md",children:[e.jsxs("div",{className:"p-4 rounded-lg bg-muted/50 border border-border",children:[e.jsx("h3",{className:"font-semibold mb-2",children:"How to export contacts from your iPhone or Mac"}),e.jsxs("ol",{className:"text-sm text-muted-foreground space-y-2 list-decimal list-inside",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"iPhone:"})," Open Contacts → Tap a contact → Share → Select All Contacts → Export as VCF"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Mac:"})," Open Contacts → Select All (⌘+A) → File → Export → Export vCard"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"iCloud.com:"})," Go to icloud.com/contacts → Select All → ⚙️ → Export vCard"]})]})]}),e.jsxs("label",{className:"block",children:[e.jsxs("div",{className:"border-2 border-dashed border-border rounded-lg p-8 text-center cursor-pointer hover:border-primary/50 hover:bg-accent/50 transition-colors",children:[e.jsx(M,{className:"h-12 w-12 mx-auto text-muted-foreground mb-4"}),e.jsx("p",{className:"font-medium mb-1",children:"Upload VCF File"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Click to select or drag and drop"})]}),e.jsx("input",{type:"file",accept:".vcf",onChange:U,className:"hidden",disabled:p})]})]}),a==="parsing"&&e.jsxs("div",{className:"text-center",children:[e.jsx(A,{className:"h-12 w-12 animate-spin text-primary mx-auto mb-4"}),e.jsxs("h2",{className:"text-lg font-semibold mb-2",children:["Parsing ",n,"..."]}),e.jsx("p",{className:"text-muted-foreground",children:"Reading your contacts"})]}),a==="saving"&&e.jsxs("div",{className:"text-center w-full max-w-sm",children:[e.jsx(A,{className:"h-12 w-12 animate-spin text-primary mx-auto mb-4"}),e.jsxs("h2",{className:"text-lg font-semibold mb-2",children:["Importing ",t," contacts..."]}),e.jsx(R,{value:_,className:"mb-2"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[i," of ",t," saved"]})]}),a==="done"&&e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center mx-auto mb-4",children:e.jsx(I,{className:"h-6 w-6 text-primary"})}),e.jsx("h2",{className:"text-lg font-semibold mb-2",children:i>0?`${i} contacts imported!`:"No contacts to import"}),e.jsx("p",{className:"text-muted-foreground mb-4",children:"Redirecting to your network..."}),e.jsx(g,{variant:"outline",onClick:()=>l("/contacts?tab=imported"),children:"Go to network"})]}),a==="error"&&e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"h-12 w-12 rounded-full bg-destructive/10 flex items-center justify-center mx-auto mb-4",children:e.jsx(I,{className:"h-6 w-6 text-destructive"})}),e.jsx("h2",{className:"text-lg font-semibold mb-2",children:"Import failed"}),e.jsx("p",{className:"text-muted-foreground mb-4",children:"Something went wrong while importing your contacts."}),e.jsxs("div",{className:"flex gap-2 justify-center",children:[e.jsx(g,{variant:"outline",onClick:()=>l(-1),children:"Go Back"}),e.jsxs(g,{onClick:T,children:[e.jsx(W,{className:"h-4 w-4 mr-2"}),"Try Again"]})]})]}),n&&a==="idle"&&e.jsxs("div",{className:"flex items-center gap-2 p-3 rounded-lg bg-muted/50 mt-4",children:[e.jsx(D,{className:"h-5 w-5 text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:n})]})]})]})};export{K 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.