1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2205,4586],{12205:(e,t,r)=>{r.r(t),r.d(t,{AddInvestmentDialog:()=>b});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),m=r(9409),p=r(18654),x=r(15258),v=r(35617),f=r(47026),y=r(10055),g=r(17496);let j={type:"",market:"TW",symbol:"",name:"",quantity:"",price:"",notes:""};function b({open:e,onOpenChange:t,accounts:r,selectedAccountId:w,onSelectedAccountIdChange:N,onCreate:k,onSuccess:S,userId:C,presentation:T="dialog"}){let[E,P]=(0,n.useState)(j),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),x=(0,n.useRef)(null),v=(0,n.useRef)(new Map),f=(0,n.useRef)(new Map),y="US"===t?m.mj:m.Uu,g="US"===t?m.pY:m.$z;return(0,n.useEffect)(()=>{"TW"!==t||(async()=>{try{for(let e of["å°ç©é»","è¯ç¼ç§","鴻海","ä¸è¯é»","å°å¡"]){let t=`tw_${e.toLowerCase()}`;if(!v.current.has(t)){let r=await (0,m.Uu)(e);if(v.current.set(t,r),r.length>0)try{let e=await (0,m.$z)(r[0].value);f.current.set(r[0].value,{price:e.price,currency:e.currency,name:e.name,industry:e.industry,timestamp:e.timestamp})}catch{}}}}catch(e){(0,p.vV)("é è¼å
¥è¡ç¥¨æå°çµæå¤±æ:",e)}})()},[t]),(0,n.useEffect)(()=>{if(x.current&&clearTimeout(x.current),!r.trim())return void c([]);let e=`${t}_${r.toLowerCase()}`;return v.current.has(e)?void c(v.current.get(e)):(x.current=setTimeout(async()=>{try{l(!0);let t=(await y(r)).map(e=>({label:e.label,value:e.value}));v.current.set(e,t),c(t)}catch(e){(0,p.vV)("æå°è¡ç¥¨å¤±æ:",e),c([])}finally{l(!1)}},300),()=>{x.current&&clearTimeout(x.current)})},[r,t,y]),{searchTerm:r,setSearchTerm:s,options:a,isSearching:i,currentPrice:o,isSearchOpen:d,setSearchOpen:h,getQuote:(0,n.useCallback)(async e=>{if(f.current.has(e))return void u(f.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};f.current.set(e,r),u(r)}catch(e){throw(0,p.vV)("åå¾è¡ç¥¨å ±å¹å¤±æ:",e),e}},[g])}}({market:"US"===E.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),m=(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,x.Z)(e);if(h.current.set(e.toLowerCase(),t),t.length>0)try{let e=await (0,x.p)(t[0].value);m.current.set(t[0].value,{price:e.nav,currency:e.currency,navDate:e.navDate})}catch{}}}catch(e){(0,p.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,x.Z)(e)).map(e=>({label:e.label,value:e.value}));h.current.set(t,r),s(r)}catch(e){(0,p.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(m.current.has(e)){let t=m.current.get(e);return l(t),t}try{let t=await (0,x.p)(e),r={price:t.nav,currency:t.currency,navDate:t.navDate};return m.current.set(e,r),l(r),r}catch(e){throw(0,p.vV)("åå¾åºéæ·¨å¼å¤±æ:",e),e}},[])}}(),q=(0,n.useRef)(null),F=(0,n.useRef)(null),$=(0,n.useRef)(!1),D=(0,n.useMemo)(()=>{let e=Number(E.quantity);return Number.isFinite(e)&&e>0?(0,y.Qg)(e):0},[E.quantity]),L=(0,n.useMemo)(()=>{if("stocks"===E.type){let e=R.currentPrice;if(!e)return 0;let t=(0,f.WC)(e.currency||"twd");return"twd"===t?e.price:(0,f.A7)(e.price,t)}let e=Number(E.price);return Number.isFinite(e)&&e>0?e:0},[E.type,R.currentPrice,E.price]),W=D*L,M=D>0&&L>0&&!!w;(0,n.useMemo)(()=>"stocks"===E.type&&R.currentPrice?R.currentPrice.currency||"TWD":"funds"===E.type&&O.currentPrice&&O.currentPrice.currency||"TWD",[E.type,R.currentPrice,O.currentPrice]);let A=(0,n.useCallback)(()=>{P(j),R.setSearchTerm(""),R.setSearchOpen(!1),O.setSearchTerm(""),O.setSearchOpen(!1)},[R,O]),J=(0,n.useCallback)(e=>{let t=R.options.find(t=>t.value===e);t&&($.current=!0,P(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]),U=(0,n.useCallback)(e=>{let t=O.options.find(t=>t.value===e);t&&($.current=!0,P(r=>({...r,symbol:e,name:t.label,type:"funds"})),O.setSearchTerm(t.label),O.getNav(e).then(e=>{if(e){let t=(0,f.WC)(e.currency||"twd"),r=Math.round(100*("twd"===t?e.price:(0,f.A7)(e.price,t)))/100;P(e=>({...e,price:r.toString()}))}}).catch(()=>{(0,h.oR)({title:"ç²ååºéæ·¨å¼å¤±æ",description:"ç¡æ³ç²åæ·¨å¼ï¼è«ç¨å¾å試",variant:"destructive"})})),O.setSearchOpen(!1)},[O]),V=async e=>{if(e?.preventDefault(),!E.type||!E.name||!E.quantity)return void(0,h.oR)({title:"é¯èª¤",description:"è«å¡«å¯«ææå¿
è¦æ¬ä½",variant:"destructive"});if(!C)return void(0,h.oR)({title:"é¯èª¤",description:"è«å
ç»å
¥å¸³è",variant:"destructive"});let r=Math.max(Number(E.quantity)||0,0),s="stocks"===E.type?Math.floor(r):(0,y.Qg)(r);if(s<=0)return void(0,h.oR)({title:"é¯èª¤",description:"stocks"===E.type?"è¡æ¸å¿
é çºå¤§æ¼ 0 çæ£æ´æ¸":"æ¸é/å®ä½å¿
é å¤§æ¼ 0",variant:"destructive"});let n={type:E.type,name:E.name,quantity:s,notes:E.notes,accountId:w||void 0};if("stocks"===E.type){if(!E.symbol||!R.currentPrice)return void(0,h.oR)({title:"é¯èª¤",description:"è«é¸æè¡ç¥¨ä¸¦çå¾
ç¾å¹è¼å
¥",variant:"destructive"});let e=R.currentPrice;n={...n,symbol:E.symbol,price:e.price,currency:e.currency,market:E.market||"TW",industry:e.industry,purchasePrice:e.price,purchasePriceTimestamp:e.timestamp??Date.now()}}else{if(!E.price)return void(0,h.oR)({title:"é¯èª¤",description:"è«è¼¸å
¥ææ¬å¹æ ¼",variant:"destructive"});n={...n,symbol:E.symbol||"",price:Math.max(Number(E.price)||0,0),currency:"TWD"}}try{await k(n),A(),t(!1),(0,h.oR)({title:"æå",description:"å·²æ°å¢æè³é
ç®"}),S?.()}catch(e){(0,h.oR)({title:"å²å失æ",description:e instanceof Error?e.message:"ç¡æ³å²åæè³è³æï¼è«ç¨å¾å試",variant:"destructive"})}},I=(e,t)=>{P(r=>
1({...r,type:e,market:t??r.market,symbol:"",name:"",price:""}))};return(0,n.useEffect)(()=>{"stocks"===E.type&&R.searchTerm.length>=2&&R.options.length>0&&!$.current&&R.setSearchOpen(!0)},[E.type,R.searchTerm,R.options.length,R.setSearchOpen]),(0,n.useEffect)(()=>{"funds"===E.type&&O.searchTerm.length>=2&&O.options.length>0&&!$.current&&O.setSearchOpen(!0)},[E.type,O.searchTerm,O.options.length,O.setSearchOpen]),(0,n.useEffect)(()=>{let t=e=>{let t=e.target;q.current?.contains(t)||F.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:T,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:V,className:"space-y-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"æè³é¡å"}),(0,s.jsxs)(i.l6,{value:E.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"===E.type&&(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å¸å ´"}),(0,s.jsxs)(i.l6,{value:E.market,onValueChange:e=>{I(E.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"===E.type&&(0,s.jsxs)("div",{ref:q,className:"relative",children:[(0,s.jsx)(c.J,{children:"è¡ç¥¨ä»£è/å稱"}),(0,s.jsx)(a.p,{placeholder:"US"===E.market?"輸å
¥ç¾è¡ä»£èï¼å¦ AAPLï¼...":"輸å
¥è¡ç¥¨ä»£èæå稱...",value:R.searchTerm,onChange:e=>{$.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:()=>J(e.value),children:[(0,s.jsx)(u.A,{className:`mr-2 h-4 w-4 shrink-0 ${E.symbol===e.value?"opacity-100":"opacity-0"}`}),e.label," (",e.value,")"]},e.value))})})]}),"funds"===E.type&&(0,s.jsxs)("div",{ref:F,className:"relative",children:[(0,s.jsx)(c.J,{children:"åºé代è/å稱"}),(0,s.jsx)(a.p,{placeholder:"輸å
¥åºéå稱æä»£è...",value:O.searchTerm,onChange:e=>{$.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:()=>U(e.value),children:[(0,s.jsx)(u.A,{className:`mr-2 h-4 w-4 shrink-0 ${E.symbol===e.value?"opacity-100":"opacity-0"}`}),e.label," (",e.value,")"]},e.value))})})]}),E.type&&"stocks"!==E.type&&"funds"!==E.type&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å稱"}),(0,s.jsx)(a.p,{value:E.name,onChange:e=>P(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:E.symbol,onChange:e=>P(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"===E.type?"1":"0.01",step:"stocks"===E.type?"1":"0.01",value:E.quantity,onChange:e=>{let t=e.target.value;("stocks"===E.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))&&P(e=>({...e,quantity:t}))},onBlur:e=>{let t=Number(e.target.value);if(""!==e.target.value&&Number.isFinite(t)&&t>0){let e="stocks"===E.type?Math.floor(t):(0,y.Qg)(t);P(t=>({...t,quantity:e.toString()}))}},placeholder:"stocks"===E.type?"輸å
¥è¡æ¸ï¼æ£æ´æ¸ï¼":"輸å
¥æ¸é"})]}),E.type&&"stocks"!==E.type&&(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å®å¹"}),(0,s.jsx)(a.p,{type:"number",value:E.price,onChange:e=>P(t=>({...t,price:e.target.value})),placeholder:"輸å
¥å®å¹"})]}),"funds"===E.type&&E.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"===E.type&&E.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:N,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))})]})]}),W>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,v.C)(W)})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)(c.J,{children:"å註ï¼é¸å¡«ï¼"}),(0,s.jsx)(l.T,{value:E.notes,onChange:e=>P(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:!M,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}}},17496:(e,t,r)=>{r.d(t,{T:()=>l});var s=r(85047),n=r(18534),a=r(31615),c=r(42165);function i({open:e,onClose:t,title:r,description:n,children:l,footer:o,wide:u}){let[d,h]=(0,a.useState)(!1);function m(){h(!1),setTimeout(t,240)}return((0,a.useEffect)(()=>{if(!e)return;let t=requestAnimationFrame(()=>h(!0));return()=>cancelAnimationFrame(t)},[e]),(0,a.useEffect)(()=>{e||h(!1)},[e]),(0,a.useEffect)(()=>{if(!e)return;let t=e=>{"Escape"===e.key&&m()};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[e]),e)?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("div",{className:"dbui-drawer-backdrop",onClick:m}),(0,s.jsxs)("div",{className:`dbui-drawer ${u?"dbui-drawer-wide":""} ${d?"open":""}`,role:"dialog","aria-modal":"true",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3 px-8 py-5",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsx)("div",{className:"text-lg font-extrabold",children:r}),n&&(0,s.jsx)("p",{className:"mt-1 text-xs text-muted-foreground",children:n})]}),(0,s.jsx)("button",{onClick:m,className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground","aria-label":"éé",children:(0,s.jsx)(c.A,{className:"h-4 w-4"})})]}),(0,s.jsx)("div",{className:"flex-1 overflow-auto px-8 pb-6",children:l}),o&&(0,s.jsx)("div",{className:"border-t border-border/40 px-8 py-4",children:o})]})]}):null}function l({presentation:e="dialog",open:t,onOpenChange:r,title:a,description:c,dialogClassName:o,drawerWide:u,children:d,footer:h}){return"drawer"===e?(0,s.jsx)(i,{open:t,onClose:()=>r(!1),title:a,description:c,wide:u,footer:h,children:d}):(0,s.jsx)(n.lG,{open:t,onOpenChange:r,children:(0,s.jsxs)(n.Cf,{className:o,children:[(0,s.jsxs)(n.c7,{children:[(0,s.jsx)(n.L3,{children:a}),c&&(0,s.jsx)(n.rr,{children:c})]}),d,h]})})}}}]);
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.