1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2205],{12205:(e,t,r)=>{r.r(t),r.d(t,{AddInvestmentDialog:()=>j});var s=r(85047),n=r(31615),a=r(866),c=r(96968),i=r(21582),l=r(10892),o=r(21410),u=r(68341),d=r(54306),h=r(82721),p=r(9409),m=r(18654),v=r(15258),x=r(35617),y=r(47026),f=r(10055),g=r(17496);let b={type:"",market:"TW",symbol:"",name:"",quantity:"",price:"",notes:""};function j({open:e,onOpenChange:t,accounts:r,selectedAccountId:w,onSelectedAccountIdChange:S,onCreate:k,onSuccess:N,userId:T,presentation:C="dialog"}){let[P,E]=(0,n.useState)(b),R=function(e={}){let{market:t="TW"}=e,[r,s]=(0,n.useState)(""),[a,c]=(0,n.useState)([]),[i,l]=(0,n.useState)(!1),[o,u]=(0,n.useState)(null),[d,h]=(0,n.useState)(!1),v=(0,n.useRef)(null),x=(0,n.useRef)(new Map),y=(0,n.useRef)(new Map),f="US"===t?p.mj:p.Uu,g="US"===t?p.pY:p.$z;return(0,n.useEffect)(()=>{"TW"!==t||(async()=>{try{for(let e of["å°ç©é»","è¯ç¼ç§","鴻海","ä¸è¯é»","å°å¡"]){let t=`tw_${e.toLowerCase()}`;if(!x.current.has(t)){let r=await (0,p.Uu)(e);if(x.current.set(t,r),r.length>0)try{let e=await (0,p.$z)(r[0].value);y.current.set(r[0].value,{price:e.price,currency:e.currency,name:e.name,industry:e.industry,timestamp:e.timestamp})}catch{}}}}catch(e){(0,m.vV)("é è¼å
¥è¡ç¥¨æå°çµæå¤±æ:",e)}})()},[t]),(0,n.useEffect)(()=>{if(v.current&&clearTimeout(v.current),!r.trim())return void c([]);let e=`${t}_${r.toLowerCase()}`;return x.current.has(e)?void c(x.current.get(e)):(v.current=setTimeout(async()=>{try{l(!0);let t=(await f(r)).map(e=>({label:e.label,value:e.value}));x.current.set(e,t),c(t)}catch(e){(0,m.vV)("æå°è¡ç¥¨å¤±æ:",e),c([])}finally{l(!1)}},300),()=>{v.current&&clearTimeout(v.current)})},[r,t,f]),{searchTerm:r,setSearchTerm:s,options:a,isSearching:i,currentPrice:o,isSearchOpen:d,setSearchOpen:h,getQuote:(0,n.useCallback)(async e=>{if(y.current.has(e))return void u(y.current.get(e));try{let t=await g(e),r={price:t.price,currency:t.currency,name:t.name,industry:t.industry,timestamp:t.timestamp};y.current.set(e,r),u(r)}catch(e){throw(0,m.vV)("åå¾è¡ç¥¨å ±å¹å¤±æ:",e),e}},[g])}}({market:"US"===P.market?"US":"TW"}),O=function(){let[e,t]=(0,n.useState)(""),[r,s]=(0,n.useState)([]),[a,c]=(0,n.useState)(!1),[i,l]=(0,n.use
1State)(null),[o,u]=(0,n.useState)(!1),d=(0,n.useRef)(null),h=(0,n.useRef)(new Map),p=(0,n.useRef)(new Map);return(0,n.useEffect)(()=>{(async()=>{try{for(let e of["å
大å°ç£50","å¯é¦å°50","åæ³°å°ç£50"])if(!h.current.has(e.toLowerCase())){let t=await (0,v.Z)(e);if(h.current.set(e.toLowerCase(),t),t.length>0)try{let e=await (0,v.p)(t[0].value);p.current.set(t[0].value,{price:e.nav,currency:e.currency,navDate:e.navDate})}catch{}}}catch(e){(0,m.vV)("é è¼å
¥åºéæå°çµæå¤±æ:",e)}})()},[]),(0,n.useEffect)(()=>{if(d.current&&clearTimeout(d.current),!e.trim())return void s([]);let t=e.toLowerCase();return h.current.has(t)?void s(h.current.get(t)):(d.current=setTimeout(async()=>{try{c(!0);let r=(await (0,v.Z)(e)).map(e=>({label:e.label,value:e.value}));h.current.set(t,r),s(r)}catch(e){(0,m.vV)("æå°åºé失æ:",e),s([])}finally{c(!1)}},300),()=>{d.current&&clearTimeout(d.current)})},[e]),{searchTerm:e,setSearchTerm:t,options:r,isSearching:a,currentPrice:i,isSearchOpen:o,setSearchOpen:u,getNav:(0,n.useCallback)(async e=>{if(p.current.has(e)){let t=p.current.get(e);return l(t),t}try{let t=await (0,v.p)(e),r={price:t.nav,currency:t.currency,navDate:t.navDate};return p.current.set(e,r),l(r),r}catch(e){throw(0,m.vV)("åå¾åºéæ·¨å¼å¤±æ:",e),e}},[])}}(),q=(0,n.useRef)(null),D=(0,n.useRef)(null),W=(0,n.useRef)(!1),M=(0,n.useMemo)(()=>{let e=Number(P.quantity);return Number.isFinite(e)&&e>0?(0,f.Qg)(e):0},[P.quantity]),$=(0,n.useMemo)(()=>{if("stocks"===P.type){let e=R.currentPrice;if(!e)return 0;let t=(0,y.WC)(e.currency||"twd");return"twd"===t?e.price:(0,y.A7)(e.price,t)}let e=Number(P.price);return Number.isFinite(e)&&e>0?e:0},[P.type,R.currentPrice,P.price]),F=M*$,J=M>0&&$>0&&!!w;(0,n.useMemo)(()=>"stocks"===P.type&&R.currentPrice?R.currentPrice.currency||"TWD":"funds"===P.type&&O.currentPrice&&O.currentPrice.currency||"TWD",[P.type,R.currentPrice,O.currentPrice]);let L=(0,n.useCallback)(()=>{E(b),R.setSearchTerm(""),R.setSearchOpen(!1),O.setSearchTerm(""),O.setSearchOpen(!1)},[R,O]),U=(0,n.useCallback)(e=>{let t=R.options.find(t=>t.value===e);t&&(W.current=!0,E(r=>({...r,symbol:e,name:t.label,type:"stocks"})),R.setSearchTerm(t.label),R.getQuote(e).catch(()=>{(0,h.oR)({title:"ç²åè¡å¹å¤±æ",description:"ç¡æ³ç²åè¡å¹ï¼è«ç¨å¾å試",variant:"destructive"})})),R.setSearchOpen(!1)},[R]),V=(0,n.useCallback)(e=>{let t=O.options.find(t=>t.value===e);t&&(W.current=!0,E(r=>({...r,symbol:e,name:t.label,type:"funds"})),O.setSearchTerm(t.label),O.getNav(e).then(e=>{if(e){let t=(0,y.WC)(e.currency||"twd"),r=Math.round(100*("twd"===t?e.price:(0,y.A7)(e.price,t)))/100;E(e=>({...e,price:r.toString()}))}}).catch(()=>{(0,h.oR)({title:"ç²ååºéæ·¨å¼å¤±æ",description:"ç¡æ³ç²åæ·¨å¼ï¼è«ç¨å¾å試",variant:"destructive"})})),O.setSearchOpen(!1)},[O]),A=async e=>{if(e?.preventDefault(),!P.type||!P.name||!P.quantity)return void(0,h.oR)({title:"é¯èª¤",description:"è«å¡«å¯«ææå¿
è¦æ¬ä½",variant:"destructive"});if(!T)return void(0,h.oR)({title:"é¯èª¤",description:"è«å
ç»å
¥å¸³è",variant:"destructive"});let r=Math.max(Number(P.quantity)||0,0),s="stocks"===P.type?Math.floor(r):(0,f.Qg)(r);if(s<=0)return void(0,h.oR)({title:"é¯èª¤",description:"stocks"===P.type?"è¡æ¸å¿
é çºå¤§æ¼ 0 çæ£æ´æ¸":"æ¸é/å®ä½å¿
é å¤§æ¼ 0",variant:"destructive"});let n={type:P.type,name:P.name,quantity:s,notes:P.notes,accountId:w||void 0};if("stocks"===P.type){if(!P.symbol||!R.currentPrice)return void(0,h.oR)({title:"é¯èª¤",description:"è«é¸æè¡ç¥¨ä¸¦çå¾
ç¾å¹è¼å
¥",variant:"destructive"});let e=R.currentPrice;n={...n,symbol:P.symbol,price:e.price,currency:e.currency,market:P.market||"TW",industry:e.industry,purchasePrice:e.price,purchasePriceTimestamp:e.timestamp??Date.now()}}else{if(!P.price)return void(0,h.oR)({title:"é¯èª¤",description:"è«è¼¸å
¥ææ¬å¹æ ¼",variant:"destructive"});n={...n,symbol:P.symbol||"",price:Math.max(Number(P.price)||0,0),currency:"TWD"}}try{await k(n),L(),t(!1),(0,h.oR)({title:"æå",description:"å·²æ°å¢æè³é
ç®"}),N?.()}catch(e){(0,h.oR)({title:"å²å失æ",description:e instanceof Error?e.message:"ç¡æ³å²åæè³è³æï¼è«ç¨å¾å試",variant:"destructive"})}},I=(e,t)=>{E(r=>
1({...r,type:e,market:t??r.market,symbol:"",name:"",price:""}))};return(0,n.useEffect)(()=>{"stocks"===P.type&&R.searchTerm.length>=2&&R.options.length>0&&!W.current&&R.setSearchOpen(!0)},[P.type,R.searchTerm,R.options.length,R.setSearchOpen]),(0,n.useEffect)(()=>{"funds"===P.type&&O.searchTerm.length>=2&&O.options.length>0&&!W.current&&O.setSearchOpen(!0)},[P.type,O.searchTerm,O.options.length,O.setSearchOpen]),(0,n.useEffect)(()=>{let t=e=>{let t=e.target;q.current?.contains(t)||D.current?.contains(t)||(R.setSearchOpen(!1),O.setSearchOpen(!1))};if(e)return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[e,R.setSearchOpen,O.setSearchOpen]),(0,s.jsx)(g.T,{presentation:C,open:e,onOpenChange:t,title:"æ°å¢æè³",description:"鏿æè³é¡å並填寫ç¸éè³è¨",dialogClassName:"max-w-lg max-h-[90vh] overflow-y-auto scrollbar-hide",drawerWide:!0,children:(0,s.jsxs)("form",{onSubmit:A,className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"æè³é¡å"}),(0,s.jsxs)(i.l6,{value:P.type,onValueChange:e=>I(e),children:[(0,s.jsx)(i.bq,{children:(0,s.jsx)(i.yv,{placeholder:"鏿é¡å"})}),(0,s.jsxs)(i.gC,{children:[(0,s.jsx)(i.eb,{value:"stocks",children:"è¡ç¥¨"}),(0,s.jsx)(i.eb,{value:"funds",children:"åºé"}),(0,s.jsx)(i.eb,{value:"bonds",children:"åµå¸"}),(0,s.jsx)(i.eb,{value:"realestate",children:"ä¸åç¢"}),(0,s.jsx)(i.eb,{value:"other",children:"å
¶ä»"})]})]})]}),"stocks"===P.type&&(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å¸å ´"}),(0,s.jsxs)(i.l6,{value:P.market,onValueChange:e=>{I(P.type,e)},children:[(0,s.jsx)(i.bq,{children:(0,s.jsx)(i.yv,{placeholder:"鏿å¸å ´"})}),(0,s.jsxs)(i.gC,{children:[(0,s.jsx)(i.eb,{value:"TW",children:"å°è¡"}),(0,s.jsx)(i.eb,{value:"US",children:"ç¾è¡"})]})]})]}),"stocks"===P.type&&(0,s.jsxs)("div",{ref:q,className:"relative",children:[(0,s.jsx)(c.J,{children:"è¡ç¥¨ä»£è/å稱"}),(0,s.jsx)(a.p,{placeholder:"US"===P.market?"輸å
¥ç¾è¡ä»£èï¼å¦ AAPLï¼...":"輸å
¥è¡ç¥¨ä»£èæå稱...",value:R.searchTerm,onChange:e=>{W.current=!1,R.setSearchTerm(e.target.value)},onFocus:()=>{(R.options.length>0||R.isSearching)&&R.setSearchOpen(!0)}}),R.isSearchOpen&&(0,s.jsx)("div",{className:"absolute left-0 right-0 top-full z-[100] mt-1 max-h-[300px] overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md scrollbar-hide",children:R.isSearching?(0,s.jsx)("div",{className:"py-6 text-center text-sm text-muted-foreground",children:"æå°ä¸..."}):R.searchTerm.length<2?(0,s.jsx)("div",{className:"py-6 text-center text-sm text-muted-foreground",children:"è«è¼¸å
¥è³å° 2 ååå
"}):0===R.options.length?(0,s.jsx)("div",{className:"py-6 text-center text-sm text-muted-foreground",children:"æ¾ä¸å°ç¸éæ¨ç"}):(0,s.jsx)("div",{className:"flex flex-col gap-0.5 py-1",children:R.options.map(e=>(0,s.jsxs)("button",{type:"button",className:"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground data-[selected]:bg-accent",onClick:()=>U(e.value),children:[(0,s.jsx)(u.A,{className:`mr-2 h-4 w-4 shrink-0 ${P.symbol===e.value?"opacity-100":"opacity-0"}`}),e.label," (",e.value,")"]},e.value))})})]}),"funds"===P.type&&(0,s.jsxs)("div",{ref:D,className:"relative",children:[(0,s.jsx)(c.J,{children:"åºé代è/å稱"}),(0,s.jsx)(a.p,{placeholder:"輸å
¥åºéå稱æä»£è...",value:O.searchTerm,onChange:e=>{W.current=!1,O.setSearchTerm(e.target.value)},onFocus:()=>{(O.options.length>0||O.isSearching)&&O.setSearchOpen(!0)}}),O.isSearchOpen&&(0,s.jsx)("div",{className:"absolute left-0 right-0 top-full z-[100] mt-1 max-h-[300px] overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md scrollbar-hide",children:O.isSearching?(0,s.jsx)("div",{className:"py-6 text-center text-sm text-muted-foreground",children:"æå°ä¸..."}):O.searchTerm.length<2?(0,s.jsx)("div",{className:"py-6 text-center text-sm text-muted-foreground",children:"è«è¼¸å
¥è³å° 2 ååå
"}):0===O.options.length?(0,s.jsx)("div",{className:"py-6 text-center text-sm text-muted-foreground",children:"æ¾ä¸å°ç¸éåºé"}):(0,s.jsx)("div",{className:"flex flex-col gap-0.5 py-1",children:O.options.map(e=>(0,s.jsxs)("button",{type:"button",className:"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground data-[selected]:bg-accent",onClick:()=>V(e.value),children:[(0,s.jsx)(u.A,{className:`mr-2 h-4 w-4 shrink-0 ${P.symbol===e.value?"opacity-100":"opacity-0"}`}),e.label," (",e.value,")"]},e.value))})})]}),P.type&&"stocks"!==P.type&&"funds"!==P.type&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å稱"}),(0,s.jsx)(a.p,{value:P.name,onChange:e=>E(t=>({...t,name:e.target.value}
1)),placeholder:"輸å
¥å稱"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"代èï¼é¸å¡«ï¼"}),(0,s.jsx)(a.p,{value:P.symbol,onChange:e=>E(t=>({...t,symbol:e.target.value})),placeholder:"輸å
¥ä»£è"})]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"æ¸é"}),(0,s.jsx)(a.p,{type:"number",min:"stocks"===P.type?"1":"0.01",step:"stocks"===P.type?"1":"0.01",value:P.quantity,onChange:e=>{let t=e.target.value;("stocks"===P.type?/^\d*$/.test(t):function(e){if(""===e)return!0;let t=Number(e);if(!Number.isFinite(t)||t<=0)return!1;let r=e.trim().split(".");return 1===r.length||r[1].length<=2}(t))&&E(e=>({...e,quantity:t}))},onBlur:e=>{let t=Number(e.target.value);if(""!==e.target.value&&Number.isFinite(t)&&t>0){let e="stocks"===P.type?Math.floor(t):(0,f.Qg)(t);E(t=>({...t,quantity:e.toString()}))}},placeholder:"stocks"===P.type?"輸å
¥è¡æ¸ï¼æ£æ´æ¸ï¼":"輸å
¥æ¸é"})]}),P.type&&"stocks"!==P.type&&(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å®å¹"}),(0,s.jsx)(a.p,{type:"number",value:P.price,onChange:e=>E(t=>({...t,price:e.target.value})),placeholder:"輸å
¥å®å¹"})]}),"funds"===P.type&&P.symbol&&(0,s.jsxs)("div",{className:"rounded-lg bg-muted p-3",children:[(0,s.jsx)("div",{className:"text-sm text-muted-foreground",children:"ææ°æ·¨å¼"}),O.currentPrice?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"text-lg font-semibold",children:[O.currentPrice.currency," ",O.currentPrice.price.toLocaleString()]}),O.currentPrice.navDate&&(0,s.jsxs)("div",{className:"text-xs text-muted-foreground mt-1",children:["æ·¨å¼æ¥æ: ",O.currentPrice.navDate]})]}):null]}),"stocks"===P.type&&P.symbol&&(0,s.jsxs)("div",{className:"rounded-lg bg-muted p-3",children:[(0,s.jsx)("div",{className:"text-sm text-muted-foreground",children:"ç¾å¹"}),R.currentPrice?(0,s.jsxs)("div",{className:"text-lg font-semibold",children:[R.currentPrice.currency||"TWD"," ",R.currentPrice.price.toLocaleString()]}):(0,s.jsx)("div",{className:"text-lg font-semibold flex items-center gap-2",children:(0,s.jsx)(d.default,{size:32})})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"éè¯å¸³æ¶"}),(0,s.jsxs)(i.l6,{value:w,onValueChange:S,children:[(0,s.jsx)(i.bq,{children:(0,s.jsx)(i.yv,{placeholder:"鏿右æ¶"})}),(0,s.jsx)(i.gC,{children:r.map(e=>(0,s.jsxs)(i.eb,{value:e.id,children:[e.name," (",e.bank,")"]},e.id))})]})]}),F>0&&(0,s.jsxs)("div",{className:"rounded-lg p-3 bg-muted",children:[(0,s.jsx)("div",{className:"text-sm text-muted-foreground",children:"é è¨éé¡"}),(0,s.jsx)("div",{className:"text-lg font-semibold",children:(0,x.C)(F)})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å註ï¼é¸å¡«ï¼"}),(0,s.jsx)(l.T,{value:P.notes,onChange:e=>E(t=>({...t,notes:e.target.value})),placeholder:"輸å
¥å註"})]}),(0,s.jsxs)("div",{className:"flex justify-end gap-2 pt-4",children:[(0,s.jsx)(o.$,{type:"button",variant:"outline",onClick:()=>t(!1),children:"åæ¶"}),(0,s.jsx)(o.$,{type:"submit",disabled:!J,children:"æ°å¢"})]})]})})}},15258:(e,t,r)=>{r.d(t,{Z:()=>n,p:()=>a});var s=r(58678);async function n(e){if(!e)return[];try{let t=await fetch(`/api/fund/search?q=${encodeURIComponent(e)}`);
1if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e?.error?.message||e?.error||t.statusText||"åºéæå°å¤±æ")}let r=await t.json(),n=(0,s.Xp)(s.ks).safeParse(r);if(!n.success)throw Error("Invalid fund search response");return n.data.data}catch(e){if(e instanceof TypeError&&"Failed to fetch"===e.message)throw Error("ç¡æ³é£æ¥å°ä¼ºæå¨ï¼è«æª¢æ¥ç¶²è·¯é£æ¥");throw e}}async function a(e){if(!e)throw Error("Fund code cannot be empty.");try{let t=await fetch(`/api/fund/nav?code=${encodeURIComponent(e)}`);if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e?.error?.message||e?.error||t.statusText||"åå¾åºéæ·¨å¼å¤±æ")}let r=await t.json(),n=(0,s.Xp)(s.wh).safeParse(r);if(!n.success)throw Error("Invalid NAV data");return n.data.data}catch(e){if(e instanceof TypeError&&"Failed to fetch"===e.message)throw Error("ç¡æ³é£æ¥å°ä¼ºæå¨ï¼è«æª¢æ¥ç¶²è·¯é£æ¥");throw e}}}}]);
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.