PageSourceSearch

https://andgo-platform.web.app/assets/Settings-B36Ct0E3.js

js andgo-platform.web.app collected 2026-10-03 12:16:56 UTC 14,537 bytes, 1 lines download raw bytes

1import{j as e,a2 as ee,_ as se,n as S,a3 as te,c as Q,h as U,a4 as V}from"./vendor-ui-CKm7ZMyW.js";import{r as i,L as Y}from"./vendor-react-BcgnEh9s.js";import{B as x,c as p,b as o,u as ae}from"./index-10Bqe08t.js";import{N as v}from"./NotificationToggle-Bqa-0X-0.js";import{C as L,c as P,b as D}from"./card-BC9cEqZn.js";import{P as ie}from"./products-CQmN0gyX.js";import{L as T,I as k}from"./label-DqFgRX5T.js";import{S as ne}from"./SEO-BnpntjxQ.js";import"./vendor-firebase-C5C_sMp4.js";const re=new Map(ie.map(a=>[a.id,a.name]));function M(a){return new Date(a).toLocaleDateString("en-AU",{day:"numeric",month:"short",year:"numeric"})}function le(a){const n=[];for(const[l,u]of Object.entries(a)){if(u.length===0)continue;const j=re.get(l)??l;n.push(`${j}: ${u.join(" + ")}`)}return n.length>0?n.join("  •  "):"no permissions"}function oe(){const[a,n]=i.useState(null),[l,u]=i.useState(null),[j,c]=i.useState(null),N=()=>{u(null),p.get("/api/oauth/integrations").then(t=>n(t.integrations??[])).catch(t=>{n([]),u(t instanceof Error?t.message:"Failed to load AI assistants"),console.error("[AIConnectorsSection] load failed:",t)})};i.useEffect(()=>{N()},[]);const w=async t=>{c(t);try{await p.delete(`/api/oauth/integrations/${t}`),o.success("Connection revoked"),N()}catch(C){o.error(C instanceof Error?C.message:"Failed to revoke")}finally{c(null)}},E=(a??[]).filter(t=>!t.revoked_at&&t.expires_at>Date.now());return e.jsxs(L,{children:[e.jsx(P,{className:"pb-4 border-b border-slate-100",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ee,{className:"h-5 w-5 text-[#0097b2]"}),e.jsx("h2",{className:"text-lg font-semibold text-slate-900",children:"AI Assistants"})]}),e.jsxs(Y,{to:"/docs/ai-connectors",className:"text-xs text-[#0097b2] hover:underline inline-flex items-center gap-1",children:["Setup guide ",e.jsx(se,{className:"h-3 w-3"})]})]})}),e.jsx(D,{className:"pt-6",children:a===null?e.jsx("div",{className:"py-6 flex items-center justify-center",children:e.jsx(S,{className:"h-5 w-5 text-[#0097b2] animate-spin"})}):l?e.jsxs("div",{className:"rounded-lg bg-red-50 border border-red-200 p-3 text-sm text-red-700",children:[e.jsx("p",{className:"font-semibold",children:"Couldn't load AI assistants"}),e.jsx("p",{className:"mt-1 text-xs",children:l}),e.jsx("button",{onClick:N,className:"mt-2 text-xs font-semibold text-red-800 underline",children:"Retry"})]}):E.length===0?e.jsxs("div",{className:"text-sm text-slate-600",children:[e.jsx("p",{children:"No AI assistants connected yet."}),e.jsxs("p",{className:"mt-2",children:["Connect Claude.ai or ChatGPT to read and manage your AndGo data."," ",e.jsx(Y,{to:"/docs/ai-connectors",className:"text-[#0097b2] hover:underline",children:"See how it works."})]})]}):e.jsx("div",{className:"divide-y divide-slate-100",children:E.map(t=>e.jsxs("div",{className:"py-4 first:pt-0 last:pb-0 flex items-start gap-4",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-sm font-semibold text-slate-900",children:t.client_name}),e.jsxs("span",{className:"text-xs text-slate-500",children:["Connected ",M(t.created_at)]})]}),e.jsx("p",{className:"mt-1 text-xs text-slate-600",children:le(t.product_scopes)}),e.jsxs("p",{className:"mt-1 text-xs text-slate-400",children:[t.last_used_at?`Last used ${M(t.last_used_at)}`:"Not yet used","  •  ","Expires ",M(t.expires_at)]})]}),e.jsx(x,{variant:"outline",size:"sm",onClick:()=>w(t.integration_id),disabled:j===t.integration_id,className:"flex-shrink-0",children:j===t.integration_id?e.jsx(S,{className:"h-3.5 w-3.5 animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx(te,{className:"h-3.5 w-3.5 mr-1.5"}),"Revoke"]})})]},t.integration_id))})})]})}function je(){const{user:a}=ae(),[n,l]=i.useState({displayName:"",email:"",phone:"",jobTitle:""}),[u,j]=i.useState(!1),[c,N]=i.useState({marketing:!0,education:!0,activity:!0,weeklyDigest:!0,push:!1,sms:!1}),[w,E]=i.useState({}),[t,C]=i.useState(!1);i.useEffect(()=>{a&&l(s=>({...s,displayName:a.displayName??"",email:a.email??""})),p.get("/api/users/me").then(s=>{s.user&&(l({displayName:s.user.displayName||(a==null?void 0:a.displayName)||"",email:s.user.email||(a==null?void 0:a.email)||"",phone:s.user.phone||"",jobTitle:s.user.jobTitle||""}),s.user.notifications&&N(s.user.notifications),s.user.orgNotificationPolicy&&E(s.user.orgNotificationPolicy))}).catch(()=>{})},[a]);const q=async()=>{j(!0);try{await p.patch("/api/users/me",{displayName:n.displayName,phone:n.phone,jobTitle:n.jobTitle}),o.success("Settings updated")}catch(s){o.error(s instanceof Error?s.message:"Failed to save")}finally{j(!1)}},H=async()=>{C(!0);try{await p.patch("/api/users/me",{notifications:c}),o.success("Notification preferences saved")}catch(s){o.error(s instanceof Error?s.message:"Failed to save")}finally{C(!1)}},y=s=>r=>{N(Z=>({...Z,[s]:r}))},[_,I]=i.useState(!1),[f,m]=i.useState("idle"),[R,B]=i.useState(""),[g,b]=i.useState(""),[A,d]=i.useState(""),[h,J]=i.useState([]),[G,O]=i.useState(!1),[$,z]=i.useState(!1);i.useEffect(()=>{p.get("/api/users/me").then(s=>{const r=s.user||s;r.totpEnabled&&I(!0),Array.isArray(r.providers)&&J(r.providers),r.providerLockEnabled===!0&&O(!0)}).catch(()=>{})},[]);const F={google:"Google",microsoft:"Microsoft","magic-link":"Email magic link"},W=async()=>
1{if(h.length===0){o.error("No sign-in providers recorded. Sign in again and retry.");return}z(!0);try{await p.post("/api/users/me/lock-provider"),O(!0),o.success(h.length===1?`Sign-in locked to ${F[h[0]]}.`:`Sign-in locked to: ${h.map(s=>F[s]).join(", ")}.`)}catch(s){o.error(s instanceof Error?s.message:"Failed to lock sign-in")}finally{z(!1)}},K=async()=>{if(g.length!==6){d("Enter a 6-digit code");return}m("verify"),d("");try{await p.post("/api/auth/2fa/enable",{code:g}),I(!0),m("idle"),B(""),b(""),o.success("Two-factor authentication enabled")}catch(s){d(s instanceof Error?s.message:"Invalid code. Try again."),m("scan")}},X=async()=>{if(g.length!==6){d("Enter your current 2FA code to disable");return}m("disabling"),d("");try{await p.post("/api/auth/2fa/reset-self",{code:g}),I(!1),m("idle"),b(""),o.success("Two-factor authentication disabled")}catch(s){d(s instanceof Error?s.message:"Invalid code"),m("disable-confirm")}};return e.jsxs("div",{className:"space-y-8",children:[e.jsx(ne,{title:"Settings",description:"Manage your profile, security, and notification preferences.",path:"/settings",noindex:!0}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight text-slate-900",children:"Settings"}),e.jsx("p",{className:"text-sm text-slate-600 mt-1",children:"Manage your profile and notification preferences."})]}),e.jsxs(L,{children:[e.jsx(P,{className:"pb-4 border-b border-slate-100",children:e.jsx("h2",{className:"text-lg font-semibold text-slate-900",children:"Profile"})}),e.jsxs(D,{className:"pt-6 space-y-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{htmlFor:"displayName",children:"Display Name"}),e.jsx(k,{id:"displayName",type:"text",value:n.displayName,onChange:s=>l(r=>({...r,displayName:s.target.value})),placeholder:"Your name"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{htmlFor:"email",children:"Email"}),e.jsx(k,{id:"email",type:"email",value:n.email,disabled:!0,className:"bg-muted text-slate-600 cursor-not-allowed"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{htmlFor:"phone",children:"Phone"}),e.jsx(k,{id:"phone",type:"tel",value:n.phone,onChange:s=>l(r=>({...r,phone:s.target.value})),placeholder:"0400 000 000"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(T,{htmlFor:"jobTitle",children:"Job Title"}),e.jsx(k,{id:"jobTitle",type:"text",value:n.jobTitle,onChange:s=>l(r=>({...r,jobTitle:s.target.value})),placeholder:"e.g. Managing Director"})]}),e.jsx("div",{className:"pt-2",children:e.jsx(x,{onClick:q,disabled:u,children:u?"Saving...":"Save Profile"})})]})]}),e.jsxs(L,{children:[e.jsx(P,{className:"pb-4 border-b border-slate-100",children:e.jsx("h2",{className:"text-lg font-semibold text-slate-900",children:"Security"})}),e.jsxs(D,{className:"pt-6",children:[e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 flex-shrink-0",children:_?e.jsx(Q,{className:"h-5 w-5 text-emerald-600"}):e.jsx(U,{className:"h-5 w-5 text-primary"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"text-sm font-semibold text-slate-900",children:"Two-Factor Authentication"}),e.jsx("p",{className:"text-sm text-slate-500 mt-0.5",children:_?"Your account is protected with an authenticator app. This applies across all MyAndGo products.":"Add an extra layer of security using an authenticator app like Google Authenticator or Authy."}),(f==="scan"||f==="verify")&&R&&e.jsxs("div",{className:"mt-4 space-y-4",children:[e.jsx("div",{className:"rounded-xl border border-slate-200 bg-white p-4 inline-block",children:e.jsx("img",{src:R,alt:"Scan this QR code",className:"w-48 h-48"})}),e.jsx("p",{className:"text-sm text-slate-600",children:"Scan this QR code with your authenticator app, then enter the 6-digit code below."}),e.jsxs("div",{className:"flex gap-3 items-start",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(k,{type:"text",inputMode:"numeric",pattern:"[0-9]*",maxLength:6,placeholder:"000000",value:g,onChange:s=>{b(s.target.value.replace(/\D/g,"").slice(0,6)),d("")},className:"w-32 text-center text-lg font-mono tracking-widest",autoFocus:!0}),A&&e.jsx("p",{className:"text-xs text-red-500",children:A})]}),e.jsx(x,{onClick:K,disabled:f==="verify"||g.length!==6,children:f==="verify"?e.jsx(S,{className:"h-4 w-4 animate-spin"}):"Verify & Enable"}),e.jsx(x,{variant:"ghost",onClick:()=>{m("idle"),B(""),b(""),d("")},children:"Cancel"})]})]}),f==="disable-confirm"&&e.jsxs("div",{className:"mt-4 space-y-3",children:[e.jsx("p",{className:"text-sm text-slate-600",children:"Enter your current 2FA code to confirm:"}),e.jsxs("div",{className:"flex gap-3 items-start",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(k,{type:"text",inputMode:"numeric",pattern:"[0-9]*",maxLength:6,placeholder:"000000",value:g,onChange:s=>{b(s.target.value.replace(/\D/g,"").slice(0,6)),d("")},className:"w-32 text-center text-lg font-mono tracking-widest",autoFocus:!0}),A&&e.jsx("p",{className:"text-xs text-red-500",children:A})]}),e.jsx(x,{variant:"destructive",size:"sm",onClick:X,disabled:g.length!==6,children:"Confirm Disable"}),e.jsx(x,{variant:"ghost",size:"sm",onClick:()=>{m("idle"),b(""),d("")},children:"Cancel"})]})]}),f==="idle"&&e.jsx("div",{className:"mt-4",children:_?e.jsxs(x,{variant:"outline",size:"sm",className:"text-red-600 hover:text-red-700 hover:bg-red-50",onClick:()=>m("disable-confirm"),children:[e.jsx(V,{className:"h-3.5 w-3.5 mr-1.5"}),"Disable 2FA"]}):e.jsx("p",{className:"text-xs text-slate-500",children:"Two-factor setup is temporarily unavailable while we improve it. It'll be back shortly."})}),f==="loading"&&e.jsxs("div",{className:"mt-4 flex items-center gap-2 text-sm text-slate-500",children:[e.jsx(S,{className:"h-4 w-4 animate-spin"}),"Generating QR code..."]}),f==="disabling"&&e.jsxs("div",{className:"mt-4 flex items-center gap-2 text-sm text-slate-500",children:[e.jsx(S,{className:"h-4 w-4 animate-spin"}),"Disabling..."]})]})]}),e.jsxs("div",{className:"mt-6 pt-6 border-t border-slate-100 flex items-start gap-4",children:[e.jsx("div",{className:"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 flex-shrink-0",children:G?e.jsx(Q,{className:"h-5 w-5 text-emerald-600"}):e.jsx(V,{className:"h-5 w-5 text-slate-400"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"text-sm font-semibold text-slate-900",children:"Sign-in protection"}),G?e.jsxs("p",{className:"text-sm text-slate-500 mt-0.5",children:["This account is locked to"," ",e.jsx("span",{className:"font-medium text-slate-900",children:h.length>0?h.map(s=>F[s]).join(" and "):"your current sign-in method"}),". Sign-in attempts via any other provider are refused."]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-slate-500 mt-0.5",children:h.length===0?"Your account currently accepts sign-in from any provider that c
1ontrols this email address.":`You've signed in with ${h.map(s=>F[s]).join(", ")}. Lock the account so no other provider can take it over.`}),e.jsx("p",{className:"text-sm text-slate-500 mt-2",children:"Locking refuses sign-in from any provider not on the list above. Add another provider by signing in with it once before you lock."}),e.jsx("div",{className:"mt-4",children:e.jsx(x,{size:"sm",onClick:W,disabled:$||h.length===0,children:$?e.jsxs(e.Fragment,{children:[e.jsx(S,{className:"h-3.5 w-3.5 mr-1.5 animate-spin"}),"Locking..."]}):e.jsxs(e.Fragment,{children:[e.jsx(U,{className:"h-3.5 w-3.5 mr-1.5"}),"Lock sign-in to current providers"]})})})]})]})]})]})]}),e.jsx(oe,{}),e.jsxs(L,{children:[e.jsx(P,{className:"pb-4 border-b border-slate-100",children:e.jsx("h2",{className:"text-lg font-semibold text-slate-900",children:"Notifications"})}),e.jsxs(D,{className:"pt-2",children:[e.jsxs("div",{className:"divide-y divide-slate-100",children:[e.jsx(v,{label:"Marketing",description:"Product updates, feature announcements, and promotions.",enabled:c.marketing,onChange:y("marketing"),locked:w.disableMarketing}),e.jsx(v,{label:"Education",description:"Tips, guides, and best practices for using MyAndGo products.",enabled:c.education,onChange:y("education"),locked:w.disableEducation}),e.jsx(v,{label:"Activity",description:"Notifications about actions in your account and products.",enabled:c.activity,onChange:y("activity"),locked:w.enforceActivityEmails}),e.jsx(v,{label:"Weekly Digest",description:"A weekly summary of activity across your products.",enabled:c.weeklyDigest,onChange:y("weeklyDigest")}),e.jsx(v,{label:"Push Notifications",description:"Browser push notifications for real-time updates.",enabled:c.push,onChange:y("push")}),e.jsx(v,{label:"SMS",description:"Text message alerts for critical account events.",enabled:c.sms,onChange:y("sms")}),e.jsx(v,{label:"Billing",description:"Invoices, payment confirmations, and subscription changes.",enabled:!0,onChange:()=>{},alwaysOn:!0})]}),e.jsx("div",{className:"pt-4",children:e.jsx(x,{onClick:H,disabled:t,children:t?"Saving...":"Save Preferences"})})]})]})]})}export{je as Settings};

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.