PageSourceSearch

https://futurecast.pro/assets/BusinessDashboard-ClfrCfzN.js

js futurecast.pro collected 2026-10-07 03:07:54 UTC 68,704 bytes, 21 lines download raw bytes

1import{r as m,u as Ke,j as e,e as xe,f as he}from"./vendor-query-Dkm4furz.js";import{l as He,g as Ve,I,C as me,b as oe,a as S,ab as ze,k as Xe,i as vt,u as wt,B as Nt}from"./index-Bxl4mrbd.js";import{P as kt,a as Ct,u as $t,D as St}from"./DashboardOutlook-mprw2yMg.js";import{D as pe,e as ke,a as fe,b as ge,c as be,d as je,f as De}from"./dialog-fR_2luuz.js";import{a as Pt,b as qt,c as Dt,g as Ut,d as Et}from"./api-KLjaDtIH.js";import{S as Rt}from"./shield-alert-DXoH6leS.js";import{S as Tt}from"./sparkles-DHvfBMhr.js";import{D as Qe}from"./download-CKwtl7Gj.js";import{C as Ne}from"./circle-alert-CwO54v2w.js";import{L as Oe}from"./loader-circle-DjPzjlot.js";import{A as At}from"./ForecastValue-CZeqdOqk.js";import{A as Ft}from"./arrow-down-DkeGbvxH.js";import{W as Lt}from"./wallet-DV55NvgC.js";import{T as ot}from"./trash-2-BR8kN1Em.js";import{P as Ye}from"./plus-CQs30v9g.js";import{M as zt}from"./ModelPerformance-D9tB0_ma.js";import{u as Ot}from"./useTrackedAssets-BN-L1xna.js";import{A as Mt}from"./AssetsPageContent-DC4tnllu.js";import"./vendor-react-C4nmQqxk.js";import"./vendor-pdf-5g-lfC8S.js";import"./vendor-charts-DHhRtk-9.js";import"./vendor-supabase-CbPlSJWC.js";import"./tabs-CopFr6zZ.js";import"./radio-group-DEhmKmH5.js";import"./index-C56ocfua.js";import"./use-mobile-BPng6iqB.js";import"./label-BTG2IkYA.js";import"./index-CDTJsEQL.js";import"./format-6laTj9Qx.js";import"./endOfMonth-B_TYLE30.js";import"./calendar-BEOG6gSY.js";import"./info-B-Y-qw7b.js";import"./ai-score-red-CBl2V13n.js";import"./arrow-up-right-D8lHT1NM.js";import"./arrow-down-right-DTiChjhD.js";import"./AssetLogo-Ciz6m55_.js";import"./usePredictions-BppvfKbe.js";import"./assetHistory-qwRNI2rI.js";import"./index-ClFOuIOv.js";import"./minus-DQE4Jm3S.js";import"./useModelPerformance-ivfY-bp7.js";import"./refresh-cw-mS3JM86U.js";import"./chevron-up-DVzZsbC7.js";import"./trophy-wlyMfIbd.js";import"./target-B-AAOORB.js";import"./chart-column-BVN1LHMh.js";import"./globe-xzL8vtQ2.js";import"./useAssetSubscriptions-Ctv7VMdh.js";import"./useDebouncedLoading-DgEnswdf.js";import"./alert-dialog-C_8izTEG.js";import"./search-Bm5Ia1_j.js";import"./sliders-horizontal-C5jw1RkM.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const It=He("CircleHelp",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]]);/**
7 * @license lucide-react v0.462.0 - ISC
8 *
9 * This source code is licensed under the ISC license.
10 * See the LICENSE file in the root directory of this source tree.
11 */const et=He("CloudUpload",[["path",{d:"M12 13v8",key:"1l5pq0"}],["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242",key:"1pljnt"}],["path",{d:"m8 17 4-4 4 4",key:"1quai1"}]]);/**
12 * @license lucide-react v0.462.0 - ISC
13 *
14 * This source code is licensed under the ISC license.
15 * See the LICENSE file in the root directory of this source tree.
16 */const Bt=He("FileSpreadsheet",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M8 13h2",key:"yr2amv"}],["path",{d:"M14 13h2",key:"un5t4a"}],["path",{d:"M8 17h2",key:"2yhykz"}],["path",{d:"M14 17h2",key:"10kma7"}]]);function Vt(t,s=!0){const a=t.replace(/[^\p{L}\p{N}\s_-]/gu," ").replace(/\s+/g," ").trim().toLowerCase().slice(0,80),[r,n]=m.useState("");m.useEffect(()=>{const u=setTimeout(()=>n(a),250);return()=>clearTimeout(u)},[a]);const d=Ke({queryKey:["asset-catalog-search",r],enabled:s&&a.length>=2&&r===a,staleTime:6e4,retry:1,queryFn:async({signal:u})=>{const{data:g,error:h}=await Ve.from("asset_lookup").select("slug, name, symbol").eq("is_active",!0).filter("asset_class","eq","crypto").or(`name.ilike.%${r}%,symbol.ilike.%${r}%,slug.ilike.%${r}%`).order("search_rank",{ascending:!1,nullsFirst:!1}).limit(20).abortSignal(u);if(h)throw h;return g??[]}}),l=a!==r;return{assets:l?[]:d.data??[],isSearching:s&&a.length>=2&&(l||d.isFetching),error:l?null:d.error,canSearch:a.length>=2,retry:d.refetch}}function Qt({onSelect:t}){const s=m.useId(),[a,r]=m.useState(""),[n,d]=m.useState(!0),[l,u]=m.useState(-1),[g,h]=m.useState(null),{assets:p,isSearching:y,error:U,canSearch:b,retry:f}=Vt(a,n&&!g);m.useEffect(()=>{var x,$;n&&l>=0&&(($=(x=document.getElementById(`${s}-option-${l}`))==null?void 0:x.scrollIntoView)==null||$.call(x,{block:"nearest"}))},[l,n,s]);const w=x=>{h(x),r(`${x.name} (${x.symbol.toUpperCase()})`),d(!1),u(-1),t(x)};return e.jsxs("div",{className:"space-y-2",children:[e.jsx(I,{role:"combobox","aria-label":"Search asset","aria-autocomplete":"list","aria-expanded":n,"aria-controls":`${s}-results`,"aria-describedby":`${s}-hint`,"aria-activedescendant":n&&l>=0&&p[l]?`${s}-option-${l}
16`:void 0,value:a,placeholder:"Search name, symbol, or slug",autoFocus:!0,autoComplete:"off","data-testid":"input-asset-slug",onFocus:()=>{g||d(!0)},onBlur:x=>{var $;($=x.currentTarget.parentElement)!=null&&$.contains(x.relatedTarget)||d(!1)},onChange:x=>{r(x.target.value),h(null),t(null),d(!0),u(-1)},onKeyDown:x=>{if(x.key==="ArrowDown"||x.key==="ArrowUp"){if(x.preventDefault(),g)return;d(!0),u($=>x.key==="ArrowDown"?Math.min($+1,p.length-1):Math.max($-1,0))}else x.key==="Enter"&&n?(x.preventDefault(),l>=0&&p[l]&&w(p[l])):x.key==="Escape"&&n&&(x.preventDefault(),x.stopPropagation(),d(!1))}}),e.jsx("p",{id:`${s}-hint`,className:"text-xs text-muted-foreground",children:g?`Selected asset: ${g.slug}`:"Search by name or ticker, then select an asset. No slug knowledge needed."}),n&&!g&&e.jsxs("div",{className:"rounded-lg border border-border bg-popover",children:[U?e.jsxs("div",{role:"alert",className:"space-y-2 p-3 text-sm",children:[e.jsx("p",{children:"Could not search assets. Please try again."}),e.jsx("button",{type:"button",className:"underline underline-offset-4",onClick:()=>{f()},children:"Retry search"})]}):y?e.jsx("p",{role:"status",className:"p-3 text-sm text-muted-foreground",children:"Searching assets…"}):b?p.length===0?e.jsx("p",{role:"status",className:"p-3 text-sm text-muted-foreground",children:"No matching assets. Try another name or symbol."}):null:e.jsx("p",{className:"p-3 text-xs text-muted-foreground",children:"Type at least 2 characters to search the asset catalog."}),e.jsx("div",{id:`${s}-results`,role:"listbox","aria-label":"Matching assets",className:"max-h-48 overflow-y-auto",children:!y&&!U&&p.map((x,$)=>e.jsxs("button",{id:`${s}-option-${$}`,type:"button",role:"option","aria-label":`${x.name} (${x.symbol.toUpperCase()}), ${x.slug}`,"aria-selected":l===$,className:`flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-sm hover:bg-accent/15 focus-visible:bg-accent/15 ${l===$?"bg-accent/15":""}`,onMouseDown:P=>P.preventDefault(),onClick:()=>w(x),children:[e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block truncate font-medium",children:x.name}),e.jsx("span",{className:"block truncate text-xs text-muted-foreground",children:x.slug})]}),e.jsx("span",{className:"shrink-0 text-xs font-semibold uppercase",children:x.symbol})]},x.slug))})]})]})}function _t({orgId:t,portfolioId:s,portfolioName:a,portfolioScope:r,userId:n,holdings:d,currentTotalValue:l,isLoading:u,error:g,onRetry:h}){const p=`${t}:${s}:${r}:${n??""}`;return e.jsxs("section",{"aria-label":`Portfolio history: ${a}`,"data-testid":"business-portfolio-chart",children:[e.jsx("h2",{className:"mb-4 break-words text-2xl font-semibold tracking-tight text-foreground sm:text-3xl","data-testid":"text-active-portfolio",children:a}),u?e.jsx(me,{className:"flex h-[300px] items-center justify-center text-sm text-muted-foreground",role:"status",children:"Loading portfolio history…"}):g?e.jsxs(me,{className:"p-6 text-sm",role:"alert",children:["Could not load this portfolio’s holdings for the chart.",e.jsx("button",{type:"button",className:"ml-2 underline",onClick:h,children:"Retry"})]}):e.jsx(kt,{holdingsSource:{key:["org",t,"holdings",s,r,n??""],holdings:d.map(y=>({asset_slug:y.assetSlug,quantity:y.quantity}))},currentTotalValue:l,assetSlugs:[...new Set(d.map(y=>y.assetSlug))],missingPriceSlugs:[...new Set(d.filter(y=>y.currentValueUsd==null).map(y=>y.assetSlug))],title:"Portfolio Value",showEstimateNote:!1},p)]})}async function lt(t){const s=await oe(t);if(!s.ok){const a=(await s.text().catch(()=>"")).slice(0,200);throw new Error(`${s.status} ${a||s.statusText}`)}return await s.json()}function Kt(t,s="workspace",a){return Ke({queryKey:s==="mine"?["org",t,"portfolios","mine",a]:["org",t,"portfolios"],queryFn:()=>lt(`/business/orgs/${t}/portfolios${s==="mine"?"?scope=mine":""}`),enabled:!!t&&(s!=="mine"||!!a),staleTime:3e4,refetchInterval:3e4})}function dt(t,s,a="workspace",r){return Ke({queryKey:a==="mine"?["org",t,"holdings",s,"mine",r]:["org",t,"holdings",s],queryFn:()=>{const n=new URLSearchParams;s!=="all"&&n.set("portfolioId",s),a==="mine"&&n.set("scope","mine");const d=n.size?`?${n.toString()}`:"";return lt(`/business/orgs/${t}/holdings${d}`)},enabled:!!t&&(a!=="mine"||!!r),staleTime:3e4,refetchInterval:3e4})}function Ht(t){const s=xe();return he({mutationFn:async a=>{const r=await oe(`/business/orgs/${t}/portfolios`,{method:"POST",body:JSON.stringify({name:a})});if(!r.ok)throw new Error(`Failed (${r.status}): ${(await r.text()).slice(0,200)}`);return await r.json()},onSuccess:()=>s.invalidateQueries({queryKey:["org",t,"portfolios"]})})}function Yt(t){const s=xe();return he({mutationFn:async a=>{const r=await oe(`/business/orgs/${t}/portfolios/${a}`,{method:"DELETE"});if(!r.ok)throw new Error(`Failed (${r.status}): ${(await r.text()).slice(0,200)}`)},onSuccess:()=>{s.invalidateQueries({queryKey:["org",t,"portfolios"]}),s.invalidateQueries({queryKey:["org",t,"holdings"]})}})}function Gt(t){const s=xe();return he({mutationFn:async a=>{const r=await oe(`/business/orgs/${t}/portfolios/${a.portfolioId}/holdings`,{method:"POST",body:JSON.stringify({assetSlug:a.assetSlug,quantity:a.quantity,acquisitionPriceUsd:a.acquisitionPriceUsd,acquisitionDate:a.acquisitionDate,
16notes:a.notes??null})});if(!r.ok)throw new Error(`Failed (${r.status}): ${(await r.text()).slice(0,200)}`);return await r.json()},onSuccess:()=>{s.invalidateQueries({queryKey:["org",t,"portfolios"]}),s.invalidateQueries({queryKey:["org",t,"holdings"]})}})}function Wt(t){const s=xe();return he({mutationFn:async a=>{const r=await oe(`/business/orgs/${t}/portfolios/${a.portfolioId}/import-address`,{method:"POST",body:JSON.stringify({address:a.address,acquisitionDate:a.acquisitionDate})});if(!r.ok)throw new Error(`Failed (${r.status}): ${(await r.text()).slice(0,200)}`);return await r.json()},onSuccess:()=>{s.invalidateQueries({queryKey:["org",t,"portfolios"]}),s.invalidateQueries({queryKey:["org",t,"holdings"]})}})}function ct(t){const s=xe();return he({mutationFn:async a=>{const r=await oe(`/business/orgs/${t}/holdings/${a}`,{method:"DELETE"});if(!r.ok)throw new Error(`Failed (${r.status}): ${(await r.text()).slice(0,200)}`)},onSuccess:()=>{s.invalidateQueries({queryKey:["org",t,"portfolios"]}),s.invalidateQueries({queryKey:["org",t,"holdings"]})}})}function Jt(t){const s=xe();return he({mutationFn:async({holdingId:a,...r})=>{const n=await oe(`/business/orgs/${t}/holdings/${a}`,{method:"PATCH",body:JSON.stringify(r)});if(!n.ok)throw new Error(`Failed (${n.status}): ${(await n.text()).slice(0,200)}`);return await n.json()},onSuccess:()=>{s.invalidateQueries({queryKey:["org",t,"portfolios"]}),s.invalidateQueries({queryKey:["org",t,"holdings"]})}})}const _e=t=>t instanceof Error?t.message:"Please try again.";function Zt({orgId:t,portfolio:s,portfolioScope:a,userId:r}){const[n,d]=m.useState(!1);return e.jsxs(pe,{open:n,onOpenChange:d,children:[e.jsx(ke,{asChild:!0,children:e.jsxs(S,{variant:"outline",size:"sm",className:"h-8 min-h-8 shrink-0 gap-1 px-2 py-1 text-[11px] [&_svg]:size-3","data-testid":`button-edit-portfolio-${s.id}`,children:[e.jsx(Ct,{className:"h-3 w-3"}),"Edit"]})}),e.jsxs(fe,{className:"max-h-[85vh] overflow-y-auto sm:max-w-2xl",children:[e.jsxs(ge,{children:[e.jsxs(be,{children:["Edit positions · ",s.name]}),e.jsx(je,{children:"Update quantities, acquisition details, or notes. Removing a position deletes its tracking record, not the asset in your wallet."})]}),n&&e.jsx(Xt,{orgId:t,portfolio:s,portfolioScope:a,userId:r},`${t}:${s.id}`)]})]})}function Xt({orgId:t,portfolio:s,portfolioScope:a,userId:r}){var d;const n=dt(t,s.id,a,r);return n.isLoading?e.jsx("p",{role:"status",children:"Loading positions…"}):n.isError?e.jsxs("div",{role:"alert",children:["Positions couldn’t load: ",_e(n.error)," ",e.jsx(S,{variant:"outline",onClick:()=>{n.refetch()},children:"Retry"})]}):(d=n.data)!=null&&d.holdings.length?e.jsx("div",{className:"space-y-4",children:n.data.holdings.map(l=>e.jsx(es,{orgId:t,holding:l},l.id))}):e.jsx("p",{className:"py-6 text-center text-sm text-muted-foreground",children:"No positions in this portfolio yet."})}function es({orgId:t,holding:s}){const[a,r]=m.useState(!1),[n,d]=m.useState(""),[l,u]=m.useState(""),[g,h]=m.useState(""),[p,y]=m.useState(""),[U,b]=m.useState(!1),f=Jt(t),w=ct(t),x=new Date().toISOString().slice(0,10),$=new Date(`${g}T00:00:00Z`),P=!g||/^\d{4}-\d{2}-\d{2}$/.test(g)&&g<=x&&Number.isFinite($.getTime())&&$.toISOString().slice(0,10)===g,E=n.trim()!==""&&Number.isFinite(Number(n))&&Number(n)>0&&(!l.trim()||Number.isFinite(Number(l))&&Number(l)>=0)&&P,F=f.isPending||w.isPending;function Y(){d(String(s.quantity)),u(s.acquisitionPriceUsd==null?"":String(s.acquisitionPriceUsd)),h(s.acquisitionDate??""),y(s.notes??""),f.reset(),w.reset(),b(!1),r(!0)}return e.jsxs("section",{className:"rounded-lg border p-4","aria-label":`Position ${s.assetName}`,"data-testid":`position-editor-${s.id}`,children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("div",{children:[e.jsxs("p",{className:"font-semibold",children:[s.assetName," ",e.jsx("span",{className:"text-xs text-muted-foreground",children:s.assetSymbol})]}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:[s.quantity.toLocaleString(void 0,{maximumFractionDigits:8})," units"]})]}),e.jsxs("div",{className:"flex gap-2",children:[!a&&e.jsx(S,{size:"sm",variant:"outline",disabled:F,onClick:Y,children:"Edit position"}),e.jsx(S,{size:"sm",variant:"outline",className:"text-destructive hover:bg-destructive/10",disabled:F,onClick:()=>{window.confirm(`Remove ${s.assetName} from this portfolio? This deletes the tracking record and cannot be undone.`)&&(b
16(!1),w.reset(),w.mutate(s.id))},children:w.isPending?"Removing…":"Remove"})]})]}),a&&e.jsxs("form",{className:"mt-4 space-y-3",onSubmit:L=>{L.preventDefault(),!(!E||F)&&f.mutate({holdingId:s.id,quantity:Number(n),acquisitionPriceUsd:l.trim()?Number(l):null,acquisitionDate:g||null,notes:p.trim()||null},{onSuccess:()=>{r(!1),b(!0)}})},children:[e.jsxs("label",{className:"block text-sm",children:["Quantity",e.jsx(I,{type:"number",min:"0",step:"any",value:n,onChange:L=>d(L.target.value),disabled:F})]}),e.jsxs("label",{className:"block text-sm",children:["Acquisition price (USD, optional)",e.jsx(I,{type:"number",min:"0",step:"any",value:l,onChange:L=>u(L.target.value),disabled:F})]}),e.jsxs("label",{className:"block text-sm",children:["Acquisition date (optional)",e.jsx(I,{type:"date",max:x,value:g,onChange:L=>h(L.target.value),disabled:F})]}),e.jsxs("label",{className:"block text-sm",children:["Notes (optional)",e.jsx(I,{maxLength:500,value:p,onChange:L=>y(L.target.value),disabled:F})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(S,{type:"submit",disabled:!E||F,children:f.isPending?"Saving…":"Save changes"}),e.jsx(S,{type:"button",variant:"ghost",disabled:F,onClick:()=>{r(!1),f.reset()},children:"Cancel"})]})]}),f.isError&&e.jsxs("p",{role:"alert",className:"mt-2 text-sm text-destructive",children:["Could not save: ",_e(f.error)]}),w.isError&&e.jsxs("p",{role:"alert",className:"mt-2 text-sm text-destructive",children:["Could not remove: ",_e(w.error)]}),U&&e.jsx("p",{role:"status",className:"mt-2 text-sm",children:"Position saved."})]})}const qe=["id","portfolioId","assetSlug","date","kind","quantity","unitPriceUsd","unitCostBasisUsd","feeUsd","transferId"],ts=new Set(["opening","buy","sell","deposit","withdrawal","reward","transfer_in","transfer_out","valuation"]);class D extends Error{constructor(s){super(s),this.name="PortfolioCsvError"}}function ss(t){const s=[];let a=[],r="",n=!1,d=!1;for(let l=0;l<t.length;l+=1){const u=t[l];if(n){u==='"'?t[l+1]==='"'?(r+='"',l+=1):(n=!1,d=!0):r+=u;continue}if(d&&u!==","&&u!=="\r"&&u!==`
17`)throw new D(`Unexpected character after a quoted value near character ${l+1}.`);if(u==='"'&&r.length===0&&!d)n=!0;else if(u===",")a.push(r),r="",d=!1;else if(u===`
18`||u==="\r")a.push(r),a.some(g=>g.trim()!=="")&&s.push(a),a=[],r="",d=!1,u==="\r"&&t[l+1]===`
19`&&(l+=1);else{if(u==='"')throw new D(`Unexpected quote near character ${l+1}.`);r+=u}}if(n)throw new D("The CSV ends inside a quoted value.");return a.push(r),a.some(l=>l.trim()!=="")&&s.push(a),s}function as(t){if(!/^\d{4}-\d{2}-\d{2}$/.test(t))return!1;const s=new Date(`${t}T00:00:00.000Z`);return!Number.isNaN(s.valueOf())&&s.toISOString().slice(0,10)===t}function $e(t,s,a,r=!1){if(t.trim()===""&&r)return;const n=Number(t);if(t.trim()===""||!Number.isFinite(n)||n<0)throw new D(`Row ${a}: ${s} must be a finite, non-negative number.`);return n}function rs(t,s){if(new TextEncoder().encode(t).byteLength>(s.maxBytes??1048576))throw new D("CSV must be 1 MB or smaller.");const r=ss(t.replace(/^\uFEFF/,""));if(r.length<2)throw new D("Add a header row and at least one ledger row.");const n=r[0].map(u=>u.trim());if(n.length!==qe.length||n.some((u,g)=>u!==qe[g]))throw new D(`Columns must be exactly: ${qe.join(", ")}.`);const d=r.slice(1);if(d.length>(s.maxRows??1e3))throw new D("CSV may contain no more than 1,000 ledger rows.");const l=new Set(s.availablePortfolioIds??[]);return d.map((u,g)=>{const h=g+2;if(u.length!==n.length)throw new D(`Row ${h}: expected ${n.length} columns, found ${u.length}.`);const p=Object.fromEntries(n.map((F,Y)=>[F,u[Y].trim()])),y=p.id,U=p.assetSlug.toLowerCase(),b=p.date,f=p.kind;if(!y||y.length>100)throw new D(`Row ${h}: id is required (100 characters maximum).`);if(!U||U.length>100)throw new D(`Row ${h}: assetSlug is required (100 characters maximum).`);if(!as(b))throw new D(`Row ${h}: date must be a real UTC calendar date in YYYY-MM-DD format.`);if(!ts.has(f))throw new D(`Row ${h}: “${p.kind}” is not a supported activity kind.`);let w=p.portfolioId;if(s.aggregate&&!w)throw new D(`Row ${h}: portfolioId is required for an aggregate report.`);if(!s.aggregate&&!w&&(w=s.portfolioId??""),!w)throw new D(`Row ${h}: portfolioId is required.`);if(s.aggregate&&l.size>0&&!l.has(w))throw new D(`Row ${h}: portfolioId “${w}” is not in the available portfolio list.`);if(!s.aggregate&&s.portfolioId&&w!==s.portfolioId)throw new D(`Row ${h}: portfolioId must match the selected portfolio.`);const x=$e(p.quantity,"quantity",h),$=$e(p.unitPriceUsd,"unitPriceUsd",h,!0),P=$e(p.unitCostBasisUsd,"unitCostBasisUsd",h,!0),E=$e(p.feeUsd,"feeUsd",h,!0);if((f==="buy"||f==="sell")&&$===void 0)throw new D(`Row ${h}: unitPriceUsd is required for ${f} activity.`);if((f==="buy"||f==="sell")&&E===void 0)throw new D(`Row ${h}: feeUsd is required for ${f} activity; enter 0 when there was no fee.`);if(f!=="opening"&&f!=="valuation"&&x<=0)throw new D(`Row ${h}: quantity must be greater than zero for ${f} activity.`);if(f==="opening"&&b>=s.startDate)throw new D(`Row ${h}: opening balance dates must precede the selected start date.`);if(f==="valuation"){if(b!==s.endDate)throw new D(`Row ${h}: valuation rows must be dated on the selected end date.`);if(x!==0||$===void 0)throw new D(`Row ${h}: a valuation needs quantity 0 and a unitPriceUsd mark.`)}else if(f!=="opening"&&(b<s.startDate||b>s.endDate))throw new D(`Row ${h}: activity must fall within the selected date range.`);if(p.transferId.length>100)throw new D(`Row ${h}: transferId must be 100 characters or fewer.`);return{id:y,portfolioId:w,assetSlug:U,date:b,kind:f,quantity:x,...$===void 0?{}:{unitPriceUsd:$},...P===void 0?{}:{unitCostBasisUsd:P},...E===void 0?{}:{feeUsd:E},...p.transferId?{transferId:p.transferId}:{}}})}function Me(t){return/[",\r\n]/.test(t)?`"${t.replace(/"/g,'""')}"`:t}const ne=()=>new Date().toISOString().slice(0,10),Ie=t=>{const s=new Date(`${ne()}T00:00:00.000Z`);return s.setUTCDate(s.getUTCDate()-t),s.toISOString().slice(0,10)},tt=()=>typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const s=Math.random()*16|0;return(t==="x"?s:s&3|8).toString(16)}),J=t=>{var s;if(t instanceof Error)return t.message;if(t&&typeof t=="object"){const a=t;
19if(typeof((s=a.error)==null?void 0:s.message)=="string")return a.error.message;if(typeof a.message=="string")return a.message}return"Please try again."},ns=t=>{var a;if(!t||typeof t!="object")return NaN;const s=t;return Number(s.status??s.statusCode??((a=s.response)==null?void 0:a.status))},B=t=>new Intl.NumberFormat().format(t);function st({orgId:t,portfolioId:s,portfolioName:a,scope:r="workspace",portfolios:n=[]}){const d=s==null,[l,u]=m.useState(!1),[g,h]=m.useState(""),[p,y]=m.useState(""),[U,b]=m.useState(""),[f,w]=m.useState(Ie(30)),[x,$]=m.useState(ne()),[P,E]=m.useState("general"),[F,Y]=m.useState("treasury"),[L,M]=m.useState(!1),[j,C]=m.useState(!1),[V,Z]=m.useState(!1),[G,X]=m.useState([]),[ee,te]=m.useState(""),[le,Q]=m.useState(""),[c,_]=m.useState(null),[W,K]=m.useState(""),[i,k]=m.useState(!1),[T,R]=m.useState(""),[ye,se]=m.useState(""),Ge=m.useRef(null);m.useEffect(()=>{if(!l)return;let o=!0;b("");const N=(q,O)=>{var re;if(o){if(!(q!=null&&q.access_token)||!((re=q.user)!=null&&re.id)){h(""),y(""),b(O||"Your session has expired. Sign in again to continue.");return}b(""),h(q.access_token),y(q.user.id)}},{data:{subscription:A}}=Ve.auth.onAuthStateChange((q,O)=>{N(O)});return Ve.auth.getSession().then(({data:q,error:O})=>{o&&N(q.session,O==null?void 0:O.message)}).catch(q=>{o&&b(J(q))}),()=>{o=!1,A.unsubscribe()}},[l]);const Ue=m.useMemo(()=>g?{Authorization:`Bearer ${g}`}:{},[g]),de=Pt(t,{query:{enabled:l&&!!g&&!!p,queryKey:[...Et(t),p]},request:{headers:Ue}}),Ee=qt({request:{headers:Ue}}),ae=Dt(t,(c==null?void 0:c.id)??W,{query:{enabled:!!g&&!!p&&!!((c==null?void 0:c.status)==="generating"||i),queryKey:[...Ut(t,(c==null?void 0:c.id)??W),p],refetchInterval:o=>{var N;return((N=o.state.data)==null?void 0:N.status)==="generating"?2500:!1},refetchOnWindowFocus:!0},request:{headers:Ue}});m.useEffect(()=>{const o=ae.data;o&&(_(o),k(!1),o.status==="ready"&&R("Report is ready. Downloading again does not use more tokens."),o.status==="failed"&&R("Report generation failed. Its token charge has been refunded."))},[ae.data]),m.useEffect(()=>{_(null),K(""),k(!1),R("")},[t,s,r,p]);const v=de.data,Re=((v==null?void 0:v.baseTokens)??50)+(L?(v==null?void 0:v.executiveSummaryTokens)??25:0)+(j?(v==null?void 0:v.reconciliationTokens)??100:0),We=v?v.purchasedTokens>=Re:!1,Ce=!!f&&!!x&&f<=x&&x<=ne(),z=(c==null?void 0:c.status)==="generating"||i||Ee.isPending,mt=!j||G.length>0&&V,Je=!!g&&!!v&&Ce&&mt&&We&&!z&&!U&&!de.isError;function Te(o,N){w(o),$(N),X([]),te(""),Z(!1),Q(""),_(null),K(""),k(!1),R("")}function xt(){const o=d?n.length?n.slice(0,2):[{id:"portfolio-id-from-workspace",name:"Replace with portfolio ID"}]:[{id:s??"",name:a}],N=f||Ie(30),A=x||ne(),q=new Date(`${N}T00:00:00.000Z`);q.setUTCDate(q.getUTCDate()-1);const O=q.toISOString().slice(0,10),re=[qe.join(",")];o.forEach((Fe,yt)=>{const Le=yt+1;re.push([`example-opening-${Le}`,Fe.id,"btc",O,"opening","0.5","","42000","0",""].map(we=>Me(we)).join(",")),re.push([`example-buy-${Le}`,Fe.id,"btc",N,"buy","0.1","44000","","2.5",""].map(we=>Me(we)).join(",")),re.push([`example-valuation-${Le}`,Fe.id,"btc",A,"valuation","0","45000","","0",""].map(we=>Me(we)).join(","))});const jt=new Blob([`\uFEFF${re.join(`\r
20`)}\r
21`],{type:"text/csv;charset=utf-8"}),Ze=URL.createObjectURL(jt),Ae=document.createElement("a");Ae.href=Ze,Ae.download="futurecast-ledger-template.csv",Ae.click(),URL.revokeObjectURL(Ze)}async function ht(o){if(Q(""),X([]),te(""),Z(!1),K(""),_(null),R(""),!!o){if(o.size>1048576){Q("This file is larger than 1 MB. Choose a smaller CSV.");return}if(!o.name.toLowerCase().endsWith(".csv")&&o.type!=="text/csv"){Q("Choose a CSV file.");return}try{const N=rs(await o.text(),{portfolioId:s,aggregate:d,startDate:f,endDate:x,availablePortfolioIds:n.map(A=>A.id),maxRows:Math.min(1e3,(v==null?void 0:v.maxTransactions)??1e3)});X(N),te(o.name),R("")}catch(N){Q(N instanceof Error?N.message:"The CSV could not be read.")}}}function pt(){return{portfolioId:s??null,scope:r,startDate:f,endDate:x,jurisdiction:P,firmType:F,executiveSummary:L,reconcile:j,...j?{ledgerComplete:V,transactions:G}:{}}}async function ft(){if(!Je)return;R(""),se(""),k(!1);const o=(c==null?void 0:c.status)==="failed"?tt():W||tt();
21K(o);const N={...pt(),requestId:o};try{const A=await Ee.mutateAsync({orgId:t,data:N});_(A),R(A.status==="ready"?"Report is ready. Downloading again does not use more tokens.":"Report generation started."),A.status==="failed"&&R("Report generation failed. Its token charge has been refunded.")}catch(A){const q=ns(A),O=Number.isFinite(q)&&q>=400&&q<500;k(!O),O&&K(""),R(O?`The server declined this request (${q}): ${J(A)} Review the price, purchased balance, and workspace access before retrying. No report was generated.`:`We couldn’t confirm the response: ${J(A)} Check this request’s status before trying again.`)}}async function gt(){if(!(!W||!g)){k(!0),R("Checking report status…");try{const o=await ae.refetch();!o.data&&o.error?R(`Status could not be confirmed: ${J(o.error)}. You can check again using the same request ID.`):o.data||R("No report status is available yet. Check again shortly using this same request ID.")}catch(o){R(`Status check failed: ${J(o)}`)}}}async function bt(){if(!(!(c!=null&&c.downloadPath)||!g)){se("");try{const o=c.downloadPath;if(!o.startsWith("/api/business/")||o.startsWith("//"))throw new Error("The report download path was not recognized. Contact your workspace administrator.");const N=await fetch(o,{headers:{Authorization:`Bearer ${g}`},credentials:"include"});if(!N.ok)throw new Error(N.status===401||N.status===403?"Your session may have expired. Sign in and try again.":`Download failed (${N.status}).`);const A=await N.blob(),q=URL.createObjectURL(A),O=document.createElement("a");O.href=q,O.download=`futurecast-portfolio-report-${c.id}.pdf`,O.click(),URL.revokeObjectURL(q)}catch(o){se(J(o))}}}function ve(o,N){i||z||(o(N),_(null),K(""),k(!1),R(""))}return e.jsxs(pe,{open:l,onOpenChange:o=>{u(o),o||h("")},children:[e.jsx(ke,{asChild:!0,children:e.jsxs(S,{type:"button",size:"sm",variant:"outline",className:"relative z-10 h-8 shrink-0 gap-1.5 px-2.5 text-xs","data-testid":`button-open-portfolio-report-${s??"aggregate"}`,children:[e.jsx(ze,{className:"h-3.5 w-3.5"})," Report"]})}),e.jsxs(fe,{className:"max-h-[92dvh] w-[calc(100vw-1rem)] max-w-3xl overflow-y-auto rounded-2xl p-0 sm:w-full",children:[e.jsx("div",{className:"border-b border-border/70 bg-[linear-gradient(120deg,hsl(var(--card)),hsl(var(--background)))] px-5 py-5 sm:px-7",children:e.jsxs(ge,{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[e.jsx("span",{className:"flex h-8 w-8 items-center justify-center rounded-lg border border-accent/40 bg-accent/15 text-foreground",children:e.jsx(ze,{className:"h-4 w-4"})}),e.jsx("span",{className:"text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground",children:"Portfolio intelligence · PDF"})]}),e.jsx(be,{className:"text-xl sm:text-2xl",children:"Build a portfolio report"}),e.jsxs(je,{className:"mt-1 max-w-xl text-sm leading-relaxed",children:[d?`${a} · an account-by-account view`:a,r==="mine"?" · portfolios you created":""]})]})}),e.jsxs("div",{className:"space-y-6 px-5 py-5 sm:px-7",children:[U&&e.jsx(Pe,{tone:"error",icon:e.jsx(Rt,{className:"h-4 w-4"}),title:"Session required",children:U}),!U&&!g&&e.jsxs("div",{className:"space-y-3","aria-label":"Loading session",children:[e.jsx("div",{className:"h-4 w-1/2 animate-pulse rounded bg-muted"}),e.jsx("div",{className:"h-16 animate-pulse rounded-xl bg-muted/70"})]}),g&&e.jsxs(e.Fragment,{children:[e.jsxs("section",{"aria-labelledby":"report-period-title",children:[e.jsxs("div",{className:"mb-3 flex flex-wrap items-end justify-between gap-2",children:[e.jsxs("div",{children:[e.jsx(at,{number:"01"}),e.jsx("h3",{id:"report-period-title",className:"mt-1 font-semibold",children:"Reporting period"})]}),e.jsx("div",{className:"flex flex-wrap gap-1.5","aria-label":"Date range presets",children:[["30 days",30],["90 days",90],["Year to date","ytd"]].map(([o,N])=>{const A=ne(),q=N==="ytd"?`${A.slice(0,4)}-01-01`:Ie(Number(N));return e.jsx("button",{type:"button",disabled:i||z,onClick:()=>Te(q,A),className:"rounded-full border border-border/80 px-2.5 py-1 text-[11px] text-muted-foreground transition-colors hover:border-foreground
21/30 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring","data-testid":`button-report-preset-${String(o).toLowerCase().replace(/ /g,"-")}`,children:o},String(o))})})]}),e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(Se,{label:"Start date",htmlFor:"portfolio-report-start",children:e.jsx(I,{id:"portfolio-report-start",type:"date",max:ne(),value:f,disabled:i||z,onChange:o=>Te(o.target.value,x),"aria-invalid":!Ce,"data-testid":"input-report-start-date"})}),e.jsx(Se,{label:"End date (UTC)",htmlFor:"portfolio-report-end",children:e.jsx(I,{id:"portfolio-report-end",type:"date",max:ne(),value:x,disabled:i||z,onChange:o=>Te(f,o.target.value),"aria-invalid":!Ce,"data-testid":"input-report-end-date"})})]}),!Ce&&e.jsx("p",{className:"mt-2 text-xs text-destructive",role:"alert",children:"Choose a valid range ending today or earlier."})]}),e.jsxs("section",{className:"grid gap-4 sm:grid-cols-2","aria-label":"Report context",children:[e.jsx(Se,{label:"Reporting jurisdiction",htmlFor:"portfolio-report-jurisdiction",children:e.jsxs("select",{id:"portfolio-report-jurisdiction",disabled:i||z,className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",value:P,onChange:o=>ve(E,o.target.value),"data-testid":"select-report-jurisdiction",children:[e.jsx("option",{value:"general",children:"General international management"}),e.jsx("option",{value:"us_gaap",children:"US GAAP"}),e.jsx("option",{value:"ifrs",children:"IFRS"}),e.jsx("option",{value:"eu_mica",children:"EU MiCA"})]})}),e.jsx(Se,{label:"Organization type",htmlFor:"portfolio-report-firm",children:e.jsxs("select",{id:"portfolio-report-firm",disabled:i||z,className:"h-10 w-full rounded-md border border-input bg-background px-3 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",value:F,onChange:o=>ve(Y,o.target.value),"data-testid":"select-report-firm-type",children:[e.jsx("option",{value:"treasury",children:"Treasury · own holdings"}),e.jsx("option",{value:"manager",children:"Manager / fund"}),e.jsx("option",{value:"custodian",children:"Custodian / broker"})]})})]}),e.jsxs("section",{className:"space-y-2.5","aria-label":"Report options",children:[e.jsx(rt,{checked:L,onChange:o=>ve(M,o),title:"Add executive summary pages",description:"A concise, branded opening with key portfolio context.",price:v?`+${B(v.executiveSummaryTokens)} tokens`:"+25 tokens",icon:e.jsx(Tt,{className:"h-4 w-4"}),testId:"toggle-report-executive-summary",disabled:i||z}),e.jsx(rt,{checked:j,onChange:o=>{i||z||(ve(C,o),o||(Z(!1),X([]),te(""),Q("")))},title:"Reconcile a transaction ledger",description:"Compare submitted record quantities with available portfolio holdings.",price:v?`+${B(v.reconciliationTokens)} tokens`:"+100 tokens",icon:e.jsx(Bt,{className:"h-4 w-4"}),testId:"toggle-report-reconciliation",disabled:i||z})]}),j&&e.jsx("section",{className:"rounded-xl border border-accent/50 bg-accent/10 p-4 sm:p-5","aria-label":"Ledger upload",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("span",{className:"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-background/70",children:e.jsx(et,{className:"h-4 w-4"})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[e.jsxs("div",{children:[e.jsx(at,{number:"02"}),e.jsx("h3",{className:"mt-1 font-semibold",children:"Supply the full period ledger"})]}),e.jsxs(S,{type:"button",variant:"outline",size:"sm",className:"h-8 gap-1.5",disabled:i||z,onClick:xt,"data-testid":"button-download-ledger-template",children:[e.jsx(Qe,{className:"h-3.5 w-3.5"})," Template"]})]}),e.jsxs("p",{className:"mt-2 text-xs leading-relaxed text-muted-foreground",children:["Include opening balances before the start, all activity in the period, and end-date valuations (quantity 0; unitPriceUsd is the mark). Every buy and sell needs unitPriceUsd and feeUsd; enter 0 when there was no fee. For other activity, a blank fee means unavailable, not zero. unitPriceUsd is a movement/execution/valuation price—not an opening or transferred acquisition cost. Opening, deposit, reward, and transfer_in rows need an explicit unitCostBasisUsd for FIFO lot costing. Buy lot cost derives from execution price plus fee. Missing basis stays unavailable; it is never inferred from market value. CSV only, up to 1 MB and ",B(Math.min(1e3,(v==null?void 0:v.maxTransactions)??1e3))," rows."]}),e.jsx("p",{className:"mt-2 rounded-md bg-background/60 px-2.5 py-2 text-[11px] font-medium text-muted-foreground",children:"Template rows are fictitious examples only—not actual holdings or historical data. Replace or remove every example before uploading."}),d&&e.jsxs("div",{className:"mt-3 rounded-lg border border-border/70 bg-background/60 p-3",children:[e.jsx("p",{className:"text-xs font-medium",children:"Portfolio ID mapping"}),e.jsx("p",{className:"mt-1 text-[11px] leading-relaxed text-muted-foreground",children:"Every row needs a portfolioId. Copy the ID—not just the name—from your workspace’s portfolio details/API. The template includes sample IDs; replace them with the correct IDs for each ledger entry."}),e.jsx("div",{className:"mt-2 max-h-24 space-y-1 overflow-y-auto",children:n.length?n.map(o=>e.jsxs("div",{className:"flex min-w-0 justify-between gap-3 text-[11px]",children:[e.jsx("span",{className:"truncate text-muted-foreground",children:o.name}),e.jsx("code",{className:"shrink-0 rounded bg-muted px-1.5 py-0.5 font-mono",children:o.id})]},o.id)):e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Portfolio ID mapping is not available yet; use the ID shown in portfolio details."})})]}),e.jsx("input",{ref:Ge,type:"file",accept:".csv,text/csv",className:"sr-only",disabled:i||z,"aria-label":"Upload transaction ledger CSV",onChange:o=>{var N;ht((N=o.target.files)==null?void 0:N[0]),o.currentTarget.value=""},"data-testid":"input-report-ledger-file"}),e.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[e.jsxs(S,{type:"button",variant:"secondary",size:"sm",disabled:i||z,onClick:()=>{var o;return(o=Ge.current)==null?void 0:o.click()},"data-testid":"button-upload-ledger",children:[e.jsx(et,{className:"mr-1.5 h-4 w-4"}),ee?"Replace CSV":"Choose CSV"]}),ee&&e.jsxs("span",{className:"min-w-0 truncate text-xs text-muted-foreground",role:"status",children:[ee," · ",G.length," rows checked"]})]}),le&&e.jsx("div",{className:"mt-3",role:"alert",children:e.jsx(Pe,{tone:"error",icon:e.jsx(Ne,{className:"h-4 w-4"}),title:"CSV needs attention",children:le})}),ee&&!le&&e.jsxs("div",{className:"mt-3 flex items-start gap-2 rounded-lg border border-emerald-700/20 bg-emerald-700/5 p-3 text-xs text-foreground",children:[e.jsx(Xe,{className:"mt-0.5 h-4 w-4 shrink-0 text-emerald-800"}),e.jsxs("span",{children:[G.length," ledger rows validated in your browser. Uploads are used for this report request."]})]}),e.jsxs("label",{className:`mt-3 flex cursor-pointer items-start gap-2.5 rounded-lg border p-3 text-xs leading-relaxed transition-colors ${V?"border-foreground
21/30 bg-background/70":"border-border/70 bg-background/40"}`,children:[e.jsx("input",{type:"checkbox",checked:V,disabled:!G.length||i||z,onChange:o=>ve(Z,o.target.checked),className:"mt-0.5 h-4 w-4 accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring","data-testid":"checkbox-ledger-complete"}),e.jsxs("span",{children:[e.jsx("strong",{className:"font-semibold",children:"Completeness attestation."})," I confirm this upload includes complete opening balances and full activity for the selected portfolios and period to the best of my knowledge. This is my attestation, not a verification of source records."]})]})]})]})}),e.jsxs("section",{className:"rounded-xl border border-border/80 bg-card/70 p-4 sm:p-5","aria-label":"Token estimate",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground",children:"Estimated report cost"}),e.jsxs("p",{className:"mt-1 text-2xl font-semibold tabular-nums tracking-tight",children:[B(Re)," ",e.jsx("span",{className:"text-sm font-medium text-muted-foreground",children:"tokens"})]})]}),e.jsx("span",{className:"rounded-full border border-border/70 bg-background/70 px-2.5 py-1 text-[11px] tabular-nums text-muted-foreground",children:v?`${B(v.purchasedTokens)} purchased`:"Balance loading"})]}),e.jsxs("div",{className:"mt-3 space-y-1 border-t border-border/60 pt-3 text-xs text-muted-foreground",children:[e.jsxs("p",{className:"flex justify-between gap-4",children:[e.jsx("span",{children:"Standard report"}),e.jsx("span",{className:"tabular-nums",children:B((v==null?void 0:v.baseTokens)??50)})]}),L&&e.jsxs("p",{className:"flex justify-between gap-4",children:[e.jsx("span",{children:"Executive summary"}),e.jsxs("span",{className:"tabular-nums",children:["+",B((v==null?void 0:v.executiveSummaryTokens)??25)]})]}),j&&e.jsxs("p",{className:"flex justify-between gap-4",children:[e.jsx("span",{children:"Ledger reconciliation"}),e.jsxs("span",{className:"tabular-nums",children:["+",B((v==null?void 0:v.reconciliationTokens)??100)]})]})]}),e.jsx("p",{className:"mt-3 text-[11px] leading-relaxed text-muted-foreground",children:"Cost is deducted from purchased tokens. Your monthly token allowance is unchanged. Server pricing and balance determine whether a request can proceed; a failed generation is refunded. Re-downloading a ready report costs nothing."}),v&&!We&&e.jsxs("p",{className:"mt-3 flex items-start gap-2 rounded-lg border border-destructive/25 bg-destructive/5 p-3 text-xs text-destructive",role:"alert","data-testid":"status-insufficient-report-tokens",children:[e.jsx(Ne,{className:"mt-0.5 h-4 w-4 shrink-0"}),"Not enough purchased tokens for this configuration. You have ",B(v.purchasedTokens),"; this report needs ",B(Re),"."]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-start gap-2 rounded-lg bg-muted/45 px-3 py-2.5 text-[11px] leading-relaxed text-muted-foreground",children:[e.jsx(It,{className:"mt-0.5 h-3.5 w-3.5 shrink-0"}),e.jsxs("p",{children:[e.jsx("strong",{className:"font-medium text-foreground",children:"Standard reports disclose missing historical ledgers."})," Reconciliation compares the submitted quantities with holdings available to Futurecast; it does not verify source records or establish completeness. Reports are informational and are not audited or a statement of compliance."]})]}),e.jsx("p",{className:"text-[11px] leading-relaxed text-muted-foreground",children:"Futurecast name and logo appear only on optional executive summary pages. Without that option, the report pages contain portfolio information without Futurecast vendor branding."})]}),de.isLoading&&e.jsx("p",{className:"text-xs text-muted-foreground",role:"status",children:"Loading server pricing and purchased balance…"}),de.isError&&e.jsxs(Pe,{tone:"error",icon:e.jsx(Ne,{className:"h-4 w-4"}),title:"Report options unavailable",children:[J(de.error)," ",e.jsx("button",{type:"button",onClick:()=>{de.refetch()},className:"ml-1 font-semibold underline underline-offset-2","data-testid":"button-retry-report-options",children:"Retry"})]}),T&&e.jsxs("div",{className:"space-y-2",role:"status","aria-live":"polite","data-testid":"status-portfolio-report",children:[e.jsxs(Pe,{tone:(c==null?void 0:c.status)==="ready"?"success":(c==null?void 0:c.status)==="failed"?"error":"info",icon:(c==null?void 0:c.status)==="ready"?e.jsx(Xe,{className:"h-4 w-4"}):(c==null?void 0:c.status)==="failed"?e.jsx(Ne,{className:"h-4 w-4"}):e.jsx(Oe,{className:`h-4 w-4 ${z?"animate-spin":""}`}),title:(c==null?void 0:c.status)==="ready"?"Report ready":(c==null?void 0:c.status)==="failed"?"Report not generated":z?"Checking report request":"Report request",children:[T,i&&e.jsxs("span",{className:"mt-1 block font-mono text-[10px]",children:["Request ID: ",W]}),(c==null?void 0:c.tokensCharged)>0&&e.jsxs("span",{className:"ml-1",children:["Server charged ",B(c.tokensCharged)," tokens."]}),(c==null?void 0:c.error)&&e.jsx("span",{className:"mt-1 block",children:c.error})]}),i&&e.jsxs(S,{type:"button",size:"sm",variant:"outline",onClick:()=>{gt()},disabled:ae.isFetching,"data-testid":"button-check-report-status",children:[ae.isFetching?e.jsx(Oe,{className:"mr-1.5 h-4 w-4 animate-spin"}):null,"Check report status"]}),(c==null?void 0:c.status)==="ready"&&c.downloadPath&&e.jsxs(S,{type:"button",size:"sm",variant:"outline",onClick:()=>{bt()},"data-testid":"button-download-portfolio-report",children:[e.jsx(Qe,{className:"mr-1.5 h-4 w-4"}),"Download PDF"]}),ye&&e.jsx("p",{className:"text-xs text-destructive",role:"alert",children:ye})]}),ae.isError&&i&&e.jsxs("p",{className:"text-xs text-destructive",role:"alert",children:["Could not confirm status: ",J(ae.error)]})]})]}),e.jsxs(De,{className:"sticky bottom-0 flex-col-reverse gap-2 border-t border-border/70 bg-background/95 px-5 py-4 backdrop-blur sm:flex-row sm:items-center sm:justify-between sm:px-7",children:[e.jsx("p",{className:"text-[11px] leading-relaxed text-muted-foreground sm:max-w-xs",children:"Server validates the final price, entitlement, and portfolio data before generation."}),e.jsxs("div",{className:"flex w-full gap-2 sm:w-auto",children:[e.jsx(S,{type:"button",variant:"ghost",className:"flex-1 sm:flex-none",onClick:()=>u(!1),children:"Close"}),e.jsxs(S,{type:"button",className:"flex-1 gap-2 sm:flex-none",disabled:!Je||(c==null?void 0:c.status)==="ready",onClick:()=>{ft()},"data-testid":"button-generate-portfolio-report",children:[z?e.jsx(Oe,{className:"h-4 w-4 animate-spin"}):e.jsx(ze,{className:"h-4 w-4"}),Ee.isPending?"Submitting…":i?"Request pending":(c==null?void 0:c.status)==="generating"?"Generating…":"Generate report",e.jsx(vt,{className:"h-3.5 w-3.5 opacity-50"})]})]})]})]})]})}function at({number:t}){return e.jsx("span",{className:"font-mono text-[10px] font-medium tracking-[0.14em] text-muted-foreground",children:t})}function Se({label:t,htmlFor:s,children:a}){return e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("label",{htmlFor:s,className:"text-xs font-medium",children:t}),a]})}function rt({checked:t,onChange:s,title:a,description:r,price:n,icon:d,testId:l,disabled:u=!1}){return e.jsxs("label",{className:`flex cursor-pointer items-start gap-3 rounded-xl border p-3.5 transition-colors ${t?"border-foreground
21/35 bg-muted/50":"border-border/70 bg-background/45 hover:bg-muted/25"}`,children:[e.jsx("input",{type:"checkbox",checked:t,disabled:u,onChange:g=>s(g.target.checked),className:"mt-1 h-4 w-4 shrink-0 accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring","data-testid":l}),e.jsx("span",{className:"mt-0.5 text-muted-foreground",children:d}),e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"block text-sm font-medium",children:a}),e.jsx("span",{className:"mt-0.5 block text-xs leading-relaxed text-muted-foreground",children:r})]}),e.jsx("span",{className:"shrink-0 pt-0.5 text-[10px] font-medium tabular-nums text-muted-foreground",children:n})]})}function Pe({tone:t,icon:s,title:a,children:r}){const n={error:"border-destructive/25 bg-destructive/5 text-destructive",success:"border-emerald-800/20 bg-emerald-800/5 text-foreground",info:"border-border/80 bg-muted/45 text-foreground"};return e.jsxs("div",{className:`flex items-start gap-2.5 rounded-lg border p-3 text-xs leading-relaxed ${n[t]}`,children:[e.jsx("span",{className:"mt-0.5 shrink-0",children:s}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"font-semibold",children:a}),e.jsx("div",{className:"mt-0.5 text-current/85",children:r})]})]})}const H=t=>t==null||!Number.isFinite(t)?"Unavailable":t.toLocaleString(void 0,{style:"currency",currency:"USD",maximumFractionDigits:2}),ut=t=>t.toLocaleString(void 0,{maximumFractionDigits:8}),ue=()=>new Date().toISOString().slice(0,10),ie=t=>t instanceof Error?t.message:"Please try again.";function is({orgId:t,role:s,portfolioScope:a="workspace",userId:r,readOnly:n=!1}){var Q,c,_,W,K;const d=!n&&(s==="owner"||s==="admin"||s==="analyst"),l=!n&&(s==="owner"||s==="admin"),[u,g]=m.useState({key:`${t}:${a}:${r??""}`,scope:"all"}),h=`${t}:${a}:${r??""}`,p=u.key===h?u.scope:"all",y=i=>g({key:h,scope:i}),U=m.useRef(null),b=Kt(t,a,r),f=$t(),w=`${t}:${a}`,x=(Q=f.preferences.businessPortfolioOrder)==null?void 0:Q[w],$=Array.isArray(x)?x.filter(i=>typeof i=="string"):[],P=new Map($.map((i,k)=>[i,k])),E=[...((c=b.data)==null?void 0:c.portfolios)??[]].sort((i,k)=>(P.get(i.id)??Number.MAX_SAFE_INTEGER)-(P.get(k.id)??Number.MAX_SAFE_INTEGER)),[F,Y]=m.useState(""),L=(i,k)=>{const T=E.map(R=>R.id);[T[i],T[i+k]]=[T[i+k],T[i]],Y(""),f.updatePreferences({businessPortfolioOrder:{...f.preferences.businessPortfolioOrder,[w]:T}},{onError:()=>Y("Your portfolio order could not be saved. Please try again.")})},M=dt(t,p,a,r),j=(_=b.data)==null?void 0:_.aggregate,C=p==="all"?null:E.find(i=>i.id===p)??null,V=Ht(t),Z=Yt(t),G=ct(t),[X,ee]=m.useState(""),[te,le]=m.useState("");return m.useEffect(()=>{u.key!==h&&(g({key:h,scope:"all"}),U.current=null)},[u.key,h]),m.useEffect(()=>{const i=u.key===h?u.scope:"all";if(i!=="all"){if(E.some(k=>k.id===i)){U.current===i&&(U.current=null);return}i!==U.current&&!b.isFetching&&g(k=>k.key===h&&k.scope!=="all"?{key:h,scope:"all"}:k)}},[h,E,b.isFetching,u.key,u.scope]),b.isLoading?e.jsxs("div",{className:"space-y-4","aria-label":"Loading portfolios","data-testid":"portfolio-loading",children:[e.jsx("div",{className:"h-28 animate-pulse rounded-xl bg-muted/60"}),e.jsx("div",{className:"h-16 animate-pulse rounded-xl bg-muted/40"}),e.jsx("div",{className:"h-56 animate-pulse rounded-xl bg-muted/40"})]}):b.isError?e.jsxs("div",{className:"rounded-xl border border-destructive/30 bg-destructive/5 p-5 text-sm",role:"alert",children:[e.jsxs("div",{className:"flex items-center gap-2 font-semibold text-destructive",children:[e.jsx(Ne,{className:"h-4 w-4"})," Portfolios didn’t load"]}),e.jsx("p",{className:"mt-1 text-muted-foreground",children:ie(b.error)}),e.jsx(S,{variant:"outline",size:"sm",className:"mt-3",onClick:()=>{b.refetch()},children:"Try again"})]}):e.jsxs("div",{className:"space-y-7","data-business-org-id":t,children:[e.jsxs("section",{className:"rounded-2xl border border-border/70 bg-card p-5 sm:p-7 shadow-sm","aria-label":"Portfolio scope",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[e.jsx("div",{className:"min-w-0 flex-1",children:e.jsx("h2",{className:"break-words text-2xl font-semibold tracking-tight","data-testid":"text-portfolio-management",children:"Portfolio Management"})}),e.jsx("div",{className:"flex flex-wrap items-end gap-3",children:d&&e.jsx(ls,{pending:V.isPending,error:V.isError?ie(V.error):"",onCreate:(i,k)=>V.mutate(i,{onSuccess:T=>{U.current=T.portfolio.id,y(T.portfolio.id),k()}})})})]}),e.jsxs("div",{role:"group","aria-label":"Workspace portfolios",className:"mt-5 grid gap-3 md:grid-cols-2 xl:grid-cols-3",children:[e.jsxs(me,{className:`relative overflow-hidden p-4 transition ${p==="all"?"border-foreground
21/70 bg-muted/30 ring-1 ring-foreground/20":"hover:border-foreground/30"}`,"data-testid":"card-portfolio-all",children:[e.jsx("div",{className:`absolute inset-y-0 left-0 w-1 ${p==="all"?"bg-foreground":"bg-transparent"}`}),e.jsx("button",{type:"button","aria-pressed":p==="all",onClick:()=>y("all"),"data-testid":"button-select-portfolio-all","aria-label":a==="mine"?"All my portfolios":"All Teams & Accounts",className:"absolute inset-0 rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"}),e.jsxs("div",{className:"pointer-events-none",children:[e.jsx("span",{className:"block text-sm font-semibold",children:a==="mine"?"All my portfolios":"All Teams & Accounts"}),e.jsxs("span",{className:"mt-1 block text-xs text-muted-foreground",children:[(j==null?void 0:j.portfolioCount)??E.length," portfolios · ",(j==null?void 0:j.holdingsCount)??0," holdings"]}),e.jsx("span",{className:"mt-4 block text-xl font-semibold tabular-nums tracking-tight",children:H(j==null?void 0:j.totalValueUsd)}),e.jsx("span",{className:`mt-0.5 block text-xs tabular-nums ${(j==null?void 0:j.unrealizedPnlUsd)==null?"text-muted-foreground":j.unrealizedPnlUsd>=0?"text-emerald-700 dark:text-emerald-400":"text-rose-700 dark:text-rose-400"}`,children:(j==null?void 0:j.unrealizedPnlUsd)==null?"P&L unavailable":`${j.unrealizedPnlUsd>0?"+":""}${H(j.unrealizedPnlUsd)} unrealized`})]}),e.jsx("div",{className:"relative z-10 mt-4 flex items-center gap-1 border-t border-border/60 pt-3 pointer-events-none [&_button]:pointer-events-auto",children:e.jsx(st,{orgId:t,portfolioName:a==="mine"?"All my portfolios":"All Teams & Accounts",scope:a,portfolios:E})})]}),E.map((i,k)=>e.jsx(os,{portfolio:i,active:p===i.id,onSelect:()=>y(i.id),actions:e.jsxs(e.Fragment,{children:[E.length>1&&e.jsxs(e.Fragment,{children:[e.jsx(S,{variant:"outline",size:"sm","aria-label":`Move ${i.name} earlier`,"data-testid":`button-move-portfolio-earlier-${i.id}`,disabled:k===0||f.isLoading||f.isError||f.isUpdating,onClick:()=>L(k,-1),children:e.jsx(At,{className:"h-4 w-4"})}),e.jsx(S,{variant:"outline",size:"sm","aria-label":`Move ${i.name} later`,"data-testid":`button-move-portfolio-later-${i.id}`,disabled:k===E.length-1||f.isLoading||f.isError||f.isUpdating,onClick:()=>L(k,1),children:e.jsx(Ft,{className:"h-4 w-4"})})]}),d&&e.jsxs(e.Fragment,{children:[e.jsx(cs,{orgId:t,portfolio:i,compact:!0}),e.jsx(ds,{orgId:t,portfolio:i,compact:!0}),e.jsx(Zt,{orgId:t,portfolio:i,portfolioScope:a,userId:r})]}),e.jsx(st,{orgId:t,portfolioId:i.id,portfolioName:i.name,scope:a,portfolios:[i]})]}),canDelete:l,onDelete:()=>{ee(""),window.confirm(`Delete “${i.name}” and all holdings in it? This cannot be undone.`)&&Z.mutate(i.id,{onSuccess:()=>{p===i.id&&y("all")},onError:T=>ee(ie(T))})},deleting:Z.isPending},i.id))]}),E.length>1&&e.jsx("p",{className:"mt-3 text-xs text-muted-foreground",children:"Use the arrows to arrange your portfolios. This order is saved for your account."}),f.isUpdating&&e.jsx("p",{role:"status",className:"mt-2 text-xs text-muted-foreground",children:"Saving portfolio order…"}),f.isError&&e.jsx("p",{role:"alert",className:"mt-2 text-sm text-destructive",children:"Your saved order couldn’t load. Refresh to try again."}),F&&e.jsx("p",{role:"alert",className:"mt-2 text-sm text-destructive",children:F}),X&&e.jsx("p",{role:"alert",className:"mt-3 text-sm text-destructive","data-testid":"status-delete-portfolio-error",children:X})]}),e.jsx(_t,{orgId:t,portfolioId:p,portfolioName:(C==null?void 0:C.name)??(a==="mine"?"All my portfolios":"All Teams & Accounts"),portfolioScope:a,userId:r,holdings:((W=M.data)==null?void 0:W.holdings)??[],currentTotalValue:(C?C.totalValueUsd:j==null?void 0:j.totalValueUsd)??null,isLoading:M.isLoading,error:M.isError?M.error??new Error("Holdings unavailable"):null,onRetry:()=>{M.refetch()}}),e.jsxs("section",{children:[e.jsx("div",{className:"mb-3 flex flex-wrap items-end justify-between gap-3",children:e.jsxs("div",{children:[e.jsxs("h3",{className:"text-base font-semibold",children:["Holdings ",e.jsxs("span",{className:"font-normal text-muted-foreground",children:["/ ",(C==null?void 0:C.name)??"all portfolios"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:C?"Positions held in this portfolio":"Combined positions, grouped by portfolio"})]})}),e.jsx(me,{className:"overflow-hidden p-0",children:M.isLoading?e.jsxs("div",{className:"space-y-3 p-5","aria-label":"Loading holdings",children:[e.jsx("div",{className:"h-5 w-1/3 animate-pulse rounded bg-muted"}),e.jsx("div",{className:"h-12 animate-pulse rounded bg-muted/60"}),e.jsx("div",{className:"h-12 animate-pulse rounded bg-muted/60"})]}):M.isError?e.jsxs("div",{className:"p-6 text-sm text-destructive",role:"alert",children:["Holdings couldn’t load: ",ie(M.error)," ",e.jsx("button",{className:"ml-2 underline",onClick:()=>{M.refetch()},children:"Retry"})]}):(((K=M.data)==null?void 0:K.holdings.length)??0)===0?e.jsxs("div",{className:"px-5 py-12 text-center",children:[e.jsx("div",{className:"mx-auto mb-3 flex h-11 w-11 items-center justify-center rounded-full bg-muted text-muted-foreground",children:e.jsx(Lt,{className:"h-5 w-5"})}),e.jsx("p",{className:"font-medium",children:E.length===0?"Create your first portfolio":"Nothing held here yet"}),e.jsx("p",{className:"mx-auto mt-1 max-w-sm text-sm text-muted-foreground",children:E.length===0?d?"Create your first portfolio to keep your work organized. It will still be visible to your organization.":"When you create a portfolio, it will appear here. Portfolio records are shared across your organization.":C?d?`Add an asset or import a public wallet into ${C.name}.`:"Holdings will appear here once a workspace editor adds them.":"Choose a portfolio above to see its holdings or add new assets."})]}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full min-w-[900px] text-sm",children:[e.jsx("thead",{className:"bg-muted/45 text-[10px] uppercase tracking-[0.12em] text-muted-foreground",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-3 text-left font-semibold",children:"Asset"}),p==="all"&&e.jsx("th",{className:"px-4 py-3 text-left font-semibold",children:"Portfolio"}),e.jsx("th",{className:"px-4 py-3 text-right font-semibold",children:"Quantity"}),e.jsx("th",{className:"px-4 py-3 text-left font-semibold",children:"Acquired"}),e.jsx("th",{className:"px-4 py-3 text-right font-semibold",children:"Cost / unit"}),e.jsx("th",{className:"px-4 py-3 text-right font-semibold",children:"Price"}),e.jsx("th",{className:"px-4 py-3 text-right font-semibold",children:"Value"}),e.jsx("th",{className:"px-4 py-3 text-right font-semibold",children:"P&L"}),d&&e.jsx("th",{"aria-label":"Actions"})]})}),e.jsx("tbody",{children:M.data.holdings.map(i=>{var ye;const k=i.acquisitionPriceUsd===null?null:i.acquisitionPriceUsd*i.quantity,T=i.currentValueUsd==null||k===null?null:i.currentValueUsd-k,R=((ye=E.find(se=>se.id===i.portfolioId))==null?void 0:ye.name)??"—";return e.jsxs("tr",{"data-testid":`row-holding-${i.id}`,className:"border-t border-border/60 hover:bg-muted/20",children:[e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex items-center gap-2.5",children:[i.assetIcon?e.jsx("img",{src:i.assetIcon,alt:"",className:"h-7 w-7 rounded-full",loading:"lazy"}):e.jsx("div",{className:"h-7 w-7 rounded-full bg-muted"}),e.jsxs("div",{children:[e.jsx("div",{className:"font-semibold",children:i.assetName}),e.jsx("div",{className:"text-[11px] uppercase tracking-wide text-muted-foreground",children:i.assetSymbol})]})]})}),p==="all"&&e.jsx("td",{className:"px-4 py-3 text-muted-foreground",children:R}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums",children:ut(i.quantity)}),e.jsx("td",{className:"px-4 py-3 text-muted-foreground",children:i.acquisitionDate??"—"}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums",children:i.acquisitionPriceUsd==null?"Not recorded":`${H(i.acquisitionPriceUsd)} ea`}),e.jsx("td",{className:"px-4 py-3 text-right tabular-nums",children:H(i.currentPriceUsd)}),e.jsx("td",{className:"px-4 py-3 text-right font-medium tabular-nums",children:H(i.currentValueUsd)}),e.jsx("td",{className:`px-4 py-3 text-right tabular-nums ${T==null?"text-muted-foreground":T>=0?"text-emerald-700 dark:text-emerald-400":"text-rose-700 dark:text-rose-400"}`,children:T==null?i.acquisitionPriceUsd==null?"Cost not recorded":"Price unavailable":`${T>=0?"+":""}${H(T)}`}),d&&e.jsx("td",{className:"px-3 py-3 text-right",children:e.jsx("button",{type:"button",onClick:()=>{le(""),window.confirm(`Remove ${i.assetName} from ${R}?`)&&G.mutate(i.id,{onError:se=>le(ie(se))})},disabled:G.isPending,"aria-label":`Remove ${i.assetName}`,"data-testid":`button-remove-holding-${i.id}`,className:"rounded-md p-2 text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",children:e.jsx(ot,{className:"h-4 w-4"})})})]},i.id)})})]})})}),te&&e.jsx("p",{role:"alert",className:"mt-2 text-sm text-destructive","data-testid":"status-delete-holding-error",children:te})]}),e.jsxs("section",{className:"grid gap-3 sm:grid-cols-3","aria-label":"Portfolio totals",children:[e.jsx(Be,{title:"Current value",value:C?C.totalValueUsd:j==null?void 0:j.totalValueUsd,detail:`${C?"Selected portfolio":a==="mine"?"Combined value · portfolios you created":"Combined organization value"}${it(C??j)}`}),e.jsx(Be,{title:"Cost basis",value:C?C.totalCostBasisUsd:j==null?void 0:j.totalCostBasisUsd,detail:`${(C==null?void 0:C.holdingsCount)??(j==null?void 0:j.holdingsCount)??0} holdings tracked${a==="mine"?" · created by you":""}${nt(C??j)}`}),e.jsx(Be,{title:"Unrealized P&L",value:C?C.unrealizedPnlUsd:j==null?void 0:j.unrealizedPnlUsd,detail:`Based on available valuations${it(C??j)}${nt(C??j)}`,pnl:!0})]}),e.jsx("p",{className:"border-t border-border/50 pt-4 text-xs leading-relaxed text-muted-foreground",children:a==="mine"?"My portfolios filters by who created each portfolio. Portfolio records and holdings remain shared with members of this organization.":"Business portfolios are shared with members of this organization and remain separate from personal Futurecast portfolios."})]})}function nt(t){return t&&t.holdingsCount>0&&t.totalCostBasisUsd==null?" · Record acquisition costs to calculate cost basis and P&L":""}function it(t){const s=t&&"unavailableHoldingsCount"in t?t.unavailableHoldingsCount:void 0;return s?` · ${s} ${s===1?"holding":"holdings"} without a current valuation`:""}function Be({title:t,value:s,detail:a,pnl:r=!1}){const n=s==null||!Number.isFinite(s);return e.jsxs(me,{className:"p-4 sm:p-5","data-testid":`metric-${t.toLowerCase().replace(/ /g,"-")}`,children:[e.jsx("p",{className:"text-[11px] font-semibold uppercase tracking-[0.13em] text-muted-foreground",children:t}),e.jsxs("p",{className:`mt-2 text-2xl font-semibold tracking-tight tabular-nums ${r&&!n?s>=0?"text-emerald-700 dark:text-emerald-400":"text-rose-700 dark:text-rose-400":""}`,children:[!n&&r&&s>0?"+":"",H(s)]}),e.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]})}function os({portfolio:t,active:s,onSelect:a,canDelete:r,onDelete:n,deleting:d,actions:l}){const u=t.unrealizedPnlUsd==null;return e.jsxs(me,{className:`relative overflow-hidden p-4 transition ${s?"border-foreground
21/70 bg-muted/30 ring-1 ring-foreground/20":"hover:border-foreground/30"}`,"data-testid":`card-portfolio-${t.id}`,children:[e.jsx("div",{className:`absolute inset-y-0 left-0 w-1 ${s?"bg-foreground":"bg-transparent"}`}),e.jsx("button",{type:"button",onClick:a,"aria-pressed":s,"aria-label":`Select portfolio ${t.name}`,"data-testid":`button-select-portfolio-${t.id}`,className:"absolute inset-0 rounded-lg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"}),e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"pointer-events-none min-w-0 flex-1 text-left",children:[e.jsx("span",{className:"flex items-center gap-2 text-sm font-semibold",children:t.name}),e.jsxs("span",{className:"mt-1 block text-xs text-muted-foreground",children:[t.holdingsCount," ",t.holdingsCount===1?"holding":"holdings"]})]}),r&&e.jsx("button",{type:"button",onClick:n,disabled:d,"aria-label":`Delete portfolio ${t.name}`,"data-testid":`button-delete-portfolio-${t.id}`,className:"relative z-10 rounded-md p-2 text-muted-foreground hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",children:e.jsx(ot,{className:"h-4 w-4"})})]}),e.jsxs("div",{className:"pointer-events-none mt-4 block w-full text-left",children:[e.jsx("span",{className:"block text-xl font-semibold tabular-nums tracking-tight",children:H(t.totalValueUsd)}),e.jsx("span",{className:`mt-0.5 block text-xs tabular-nums ${u?"text-muted-foreground":t.unrealizedPnlUsd>=0?"text-emerald-700 dark:text-emerald-400":"text-rose-700 dark:text-rose-400"}`,children:u?"P&L unavailable":`${t.unrealizedPnlUsd>0?"+":""}${H(t.unrealizedPnlUsd)} unrealized`})]}),l&&e.jsx("div",{className:"relative z-10 mt-4 flex flex-wrap items-center gap-1 border-t border-border/60 pt-3 pointer-events-none [&_button]:pointer-events-auto","data-testid":`portfolio-actions-${t.id}`,children:l})]})}function ls({pending:t,error:s,onCreate:a}){const[r,n]=m.useState(!1),[d,l]=m.useState("");return e.jsxs(pe,{open:r,onOpenChange:n,children:[e.jsx(ke,{asChild:!0,children:e.jsxs(S,{size:"sm",className:"shrink-0",children:[e.jsx(Ye,{className:"mr-1.5 h-4 w-4"}),"New portfolio"]})}),e.jsxs(fe,{children:[e.jsxs(ge,{children:[e.jsx(be,{children:"Create a shared portfolio"}),e.jsx(je,{children:"Set up a named book for the organization’s shared holdings."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{htmlFor:"portfolio-name",className:"text-sm font-medium",children:"Portfolio name"}),e.jsx(I,{id:"portfolio-name",value:d,onChange:u=>l(u.target.value),placeholder:"Northstar treasury",maxLength:80,autoFocus:!0,"data-testid":"input-portfolio-name"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Visible to every member of this workspace."}),s&&e.jsx("p",{role:"alert",className:"text-sm text-destructive",children:s})]}),e.jsxs(De,{children:[e.jsx(S,{variant:"ghost",onClick:()=>n(!1),children:"Cancel"}),e.jsx(S,{disabled:!d.trim()||t,onClick:()=>{d.trim()&&a(d.trim(),()=>{n(!1),l("")})},"data-testid":"button-create-portfolio",children:t?"Creating…":"Create portfolio"})]})]})]})}function ds({orgId:t,portfolio:s,compact:a=!1}){const[r,n]=m.useState(!1),[d,l]=m.useState(""),[u,g]=m.useState(""),[h,p]=m.useState(""),[y,U]=m.useState(ue()),b=Gt(t);function f(){l(""),g(""),p(""),U(ue()),b.reset()}const w=Number(u),x=h.trim()===""?null:Number(h),$=!!d.trim()&&Number.isFinite(w)&&w>0&&(x===null||Number.isFinite(x)&&x>=0);return e.jsxs(pe,{open:r,onOpenChange:P=>{n(P),P||f()},children:[e.jsx(ke,{asChild:!0,children:e.jsxs(S,{size:"sm",className:a?"h-8 min-h-8 shrink-0 gap-1 px-2 py-1 text-[11px] [&_svg]:size-3":"h-9","data-testid":`button-open-add-holding-${s.id}`,children:[e.jsx(Ye,{className:a?"h-3 w-3":"mr-1 h-4 w-4"}),"Add"]})}),e.jsxs(fe,{children:[e.jsxs(ge,{children:[e.jsxs(be,{children:["Add holding to ",s.name]}),e.jsx(je,{children:"Record an asset position and optional cost details."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx(ce,{label:"Asset",children:e.jsx(Qt,{onSelect:P=>l((P==null?void 0:P.slug)??"")})}
21),e.jsx(ce,{label:"Quantity",children:e.jsx(I,{type:"number",inputMode:"decimal",value:u,onChange:P=>g(P.target.value),placeholder:"0.5",min:"0",step:"any","data-testid":"input-holding-quantity"})}),e.jsx(ce,{label:"Acquisition price (USD, optional)",children:e.jsx(I,{type:"number",inputMode:"decimal",value:h,onChange:P=>p(P.target.value),placeholder:"65000",min:"0",step:"any","data-testid":"input-acquisition-price"})}),e.jsxs(ce,{label:"Acquisition date",children:[e.jsx(I,{type:"date",value:y,onChange:P=>U(P.target.value),max:ue(),"data-testid":"input-acquisition-date"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Used for tax-lot reporting. Leave empty if unknown."})]}),b.isError&&e.jsx("p",{role:"alert",className:"text-sm text-destructive",children:ie(b.error)})]}),e.jsxs(De,{children:[e.jsx(S,{variant:"ghost",onClick:()=>n(!1),children:"Cancel"}),e.jsx(S,{disabled:!$||b.isPending,onClick:()=>b.mutate({portfolioId:s.id,assetSlug:d.trim().toLowerCase(),quantity:w,acquisitionPriceUsd:x,acquisitionDate:y||null},{onSuccess:()=>{n(!1),f()}}),children:b.isPending?"Adding…":"Add holding"})]})]})]})}function cs({orgId:t,portfolio:s,compact:a=!1}){const[r,n]=m.useState(!1),[d,l]=m.useState(""),[u,g]=m.useState(ue()),[h,p]=m.useState(""),y=Wt(t);function U(){l(""),g(ue()),p(""),y.reset()}return e.jsxs(pe,{open:r,onOpenChange:b=>{n(b),b||U()},children:[e.jsx(ke,{asChild:!0,children:e.jsxs(S,{variant:"outline",size:"sm",className:a?"h-8 min-h-8 shrink-0 gap-1 px-2 py-1 text-[11px] [&_svg]:size-3":"h-9","data-testid":`button-open-import-wallet-${s.id}`,children:[e.jsx(Qe,{className:a?"h-3 w-3":"mr-1 h-4 w-4"}),"Auto"]})}),e.jsxs(fe,{children:[e.jsxs(ge,{children:[e.jsxs(be,{children:["Import wallet into ",s.name]}),e.jsx(je,{children:"Look up a public address and add its native balance to this portfolio."})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs(ce,{label:"Public address",children:[e.jsx(I,{value:d,onChange:b=>l(b.target.value),placeholder:"bc1… / 0x… / Solana address",autoFocus:!0,spellCheck:!1,"data-testid":"input-wallet-address"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Read-only lookup of the native balance. No signature is requested and funds cannot be moved."})]}),e.jsx(ce,{label:"Acquisition date",children:e.jsx(I,{type:"date",value:u,onChange:b=>g(b.target.value),max:ue()})}),y.isError&&e.jsx("p",{role:"alert",className:"text-sm text-destructive",children:ie(y.error)}),h&&e.jsx("p",{role:"status",className:"text-sm text-emerald-700 dark:text-emerald-400",children:h})]}),e.jsxs(De,{children:[e.jsx(S,{variant:"ghost",onClick:()=>n(!1),children:"Close"}),e.jsx(S,{disabled:!d.trim()||y.isPending,onClick:()=>y.mutate({portfolioId:s.id,address:d.trim(),acquisitionDate:u||null},{onSuccess:b=>{if(!b.inserted)p(`${b.chain.toUpperCase()} address checked — no balance to import.`);else{const f=b.holdings.map(w=>`${ut(w.quantity)} ${w.symbol}`).join(", ");p(`Imported ${f} from ${b.chain}.`),l("")}}}),children:y.isPending?"Looking up…":"Import wallet"})]})]})]})}function ce({label:t,children:s}){return e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"text-sm font-medium",children:t}),s]})}function us({orgId:t}){const{assets:s,isLoading:a}=Ot(),[r,n]=m.useState(!1),d=l=>`/business/app/assets/${encodeURIComponent(l)}?orgId=${encodeURIComponent(t)}`;return e.jsxs("section",{"data-testid":"business-tracked-assets",children:[a?e.jsx("div",{role:"status",className:"rounded-xl border border-border p-5",children:"Loading tracked assets…"}):e.jsx(St,{title:"Tracked Assets",assetSlugs:s.map(l=>l.slug),assetNames:Object.fromEntries(s.map(l=>[l.slug,l.name])),assetDetailsHref:d,actions:e.jsxs(S,{size:"sm",className:"gap-1.5",onClick:()=>n(!0),children:[e.jsx(Ye,{className:"h-4 w-4"}),"Add assets"]})}),e.jsx(pe,{open:r,onOpenChange:n,children:e.jsxs(fe,{className:"max-w-5xl max-h-[85dvh] overflow-y-auto",children:[e.jsxs(ge,{children:[e.jsx(be,{children:"Add tracked assets"}),e.jsx(je,{children:"This personal list is shared with your consumer view. Your plan’s asset limit still applies."})]}),r&&e.jsx(Mt,{assetDetailsHref:d})]})})]})}function ua(){const{user:t}=wt();return e.jsx(Nt,{pageTitle:"Dashboard",children:s=>e.jsx(ms,{orgId:s.orgId,role:s.role,userId:t==null?void 0:t.id},`${s.orgId}:${(t==null?void 0:t.id)??"pending"}`)})}function ms({orgId:t,role:s,userId:a}){return e.jsxs("div",{className:"space-y-7",children:[e.jsx(is,{orgId:t,role:s,userId:a,portfolioScope:"workspace"}),e.jsx(us,{orgId:t}),e.jsx(zt,{})]})}
21export{ua 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.