PageSourceSearch

https://xynergy.ai/_next/static/chunks/6803-5974cc079e046f3e.js

js xynergy.ai collected 2026-10-05 16:01:51 UTC 178,456 bytes, 8 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6803],{8180:(e,t,s)=>{s.d(t,{dE:()=>J,L4:()=>B,tp:()=>$,yO:()=>Z,Pl:()=>b,nh:()=>E,nH:()=>I});var a=s(85047),r=s(31615),i=s(26052),l=s.n(i),n=s(21410),c=s(866),d=s(96968),o=s(62557),u=s(6386),m=s(82520),h=s(11787),x=s(41178),p=s(73521),f=s(46377),j=s(4153),v=s(83298),g=s(34961);let y=j.Bm.presetAmounts;function b(){let{user:e}=(0,p.A)(),t=(0,f.useRouter)(),{toast:s}=(0,x.dj)(),{loading:i,createSponsorship:g}=(0,v.i)(),[y,b]=(0,r.useState)("onetime"),[N,k]=(0,r.useState)(600),[C,A]=(0,r.useState)(""),[S,E]=(0,r.useState)(!1),[I,R]=(0,r.useState)(!1),[T,$]=(0,r.useState)(""),[P,D]=(0,r.useState)(""),F=j.Bm.paymentDisabled,_=j.Bm.minCustomAmount,V=()=>{if(S){let e=parseInt(C,10);return Number.isFinite(e)?e:0}return N},B=async()=>{if(F)return;if(!e)return void t.push(`/auth?redirect=${encodeURIComponent("/sponsor")}`);let a=V();if(a<_)return void s({variant:"destructive",title:"金額不足",description:`最低贊助金額為 NT$${_}`});if(I&&!T.trim())return void s({variant:"destructive",title:"請填寫顯示名稱",description:"選擇顯示於贊助牆時需填寫名稱"});try{await g({type:y,amount:a,displayOnWall:I,displayName:T.trim()||void 0,message:P.trim()||void 0})}catch(e){s({variant:"destructive",title:"贊助失敗",description:e instanceof Error?e.message:"請稍後再試"})}};return(0,a.jsxs)(m.Zp,{id:"sponsor-panel",className:"border-primary/20 shadow-lg",children:[(0,a.jsxs)(m.aR,{children:[(0,a.jsx)(m.ZB,{children:"支持我們"}),(0,a.jsx)(m.BT,{children:"選擇一次性或每月贊助,幫助平台持續運營。所有個人功能已免費開放,贊助純為支持營運。"})]}),(0,a.jsxs)(m.Wu,{className:"space-y-6",children:[(0,a.jsxs)(u.tU,{value:y,onValueChange:e=>b(e),children:[(0,a.jsxs)(u.j7,{className:"grid w-full grid-cols-2",children:[(0,a.jsx)(u.Xi,{value:"onetime",children:"一次性"}),(0,a.jsx)(u.Xi,{value:"monthly",children:"每月"})]}),(0,a.jsx)(u.av,{value:"onetime",className:"mt-4 space-y-4",children:(0,a.jsx)(w,{selectedAmount:N,setSelectedAmount:k,customAmount:C,setCustomAmount:A,useCustom:S,setUseCustom:E,minAmount:_})}),(0,a.jsx)(u.av,{value:"monthly",className:"mt-4 space-y-4",children:(0,a.jsx)(w,{selectedAmount:N,setSelectedAmount:k,customAmount:C,setCustomAmount:A,useCustom:S,setUseCustom:E,minAmount:_})})]}),(0,a.jsxs)("div",{className:"space-y-3 rounded-lg border p-4 bg-muted/30",children:[(0,a.jsxs)("div",{className:"flex items-start gap-3",children:[(0,a.jsx)(o.S,{id:"displayOnWall",checked:I,onCheckedChange:e=>R(!0===e)}),(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)(d.J,{htmlFor:"displayOnWall",className:"cursor-pointer",children:"願意顯示於贊助牆(可選)"}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"勾選後可填寫公開顯示名稱與留言"})]})]}),I&&(0,a.jsxs)("div",{className:"space-y-3 pt-2",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)(d.J,{htmlFor:"displayName",children:"顯示名稱"}),(0,a.jsx)(c.p,{id:"displayName",value:T,onChange:e=>$(e.target.value),placeholder:"您希望公開顯示的名稱",maxLength:50})]}),(0,a.jsxs)("div",{children:[(0,a.jsx)(d.J,{htmlFor:"message",children:"留言(選填)"}),(0,a.jsx)(c.p,{id:"message",value:P,onChange:e=>D(e.target.value),placeholder:"給團隊的一句話",maxLength:200})]})]})]}),F?(0,a.jsxs)("div",{className:"rounded-lg border border-dashed border-yellow-500/50 bg-yellow-500/5 p-4 text-center",children:[(0,a.jsx)("p",{className:"font-medium text-yellow-700 dark:text-yellow-400",children:"贊助功能即將開放"}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground mt-1",children:"我們正在準備金流整合,敬請期待"})]}):(0,a.jsxs)(n.$,{className:"w-full",size:"lg",onClick:B,disabled:i,children:[i&&(0,a.jsx)(h.A,{className:"mr-2 h-4 w-4 animate-spin"}),e?`前往付款 NT$${V().toLocaleString()}`:"登入後贊助"]}),!e&&!F&&(0,a.jsxs)("p",{className:"text-center text-sm text-muted-foreground",children:["尚未登入?"," ",(0,a.jsx)(l(),{href:`/auth?redirect=${encodeURIComponent("/sponsor")}`,className:"text-primary underline",children:"立即登入"})]})]})]})}function w({selectedAmount:e,setSelectedAmount:t,customAmount:s,setCustomAmount:r,useCustom:i,setUseCustom:l,minAmount:u}){return(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsx)("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2",children:y.map(s=>(0,a.jsxs)(n.$,{type:"button",variant:i||e!==s?"outline":"default",className:(0,g.cn)("h-12 text-base font-semibold"),onClick:()=>{l(!1),t(s)},children:["NT$",s]},s))}),(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)(o.S,{id:"useCustom",checked:i,onCheckedChange:e=>l(!0===e)}),(0,a.jsxs)(d.J,{htmlFor:"useCustom",className:"shrink-0 cursor-pointer",children:["自訂金額(最低 NT$",u,")"]}),(0,a.jsx)(c.p,{type:"number",min:u,step:1,value:s,onChange:e=>{l(!0),r(e.target.value)},placeholder:String(u),className:"max-w-[140px]"})]})]})}var N=s(35617),k=s(9),C=s(51577),A=s(26364),S=s(18654);function E(){let{stats:e,loading:t}=function(){let[e,t]=(0,r.useState)(null),[s,a]=(0,r.useState)(!0);return(0,r.useEffect)(()=>{let e=!1;return(async()=>{try{let s=await fetch("/api/sponsor/stats");if(!s.ok)throw Error("fetch failed");let a=await s.json();e||t(a)}catch(s){(0,S.vV)("useSponsorStats failed:",s),e||t({totalAmount:0,sponsorCount:0,activeMonthlyCount:0})}finally{e||a(!1)}})(),()=>{e=!0}},[]),{stats:e,loading:s}}();if(t)return(0,a.jsx)("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-4 animate-pulse",children:[1,2,3].map(e=>(0,a.jsx)("div",{className:"h-24 rounded-xl bg-muted"},e))});let s=[{icon:k.A,label:"累計贊助",value:(0,N.C)(e?.totalAmount??0,{showSymbol:!0})},{icon:C.A,label:"贊助者",value:String(e?.sponsorCount??0)},{icon:A.A,label:"每月定期",value:String(e?.activeMonthlyCount??0)}];return(0,a.jsx)("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-4",children:s.map(({icon:e,label:t,value:s})=>(0,a.jsxs)("div",{className:"rounded-xl border bg-card p-6 text-center shadow-sm",children:[(0,a.jsx)(e,{className:"mx-auto h-8 w-8 text-primary mb-2"}),(0,a.jsx)("p",{className:"text-2xl font-bold",children:s}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:t})]},t))})}function I(){let e=Array.from({length:8},(e,t)=>({id:`placeholder-${t}`,name:"贊助者"}));return(0,a.jsxs)("section",{className:"space-y-4",children:[(0,a.jsx)("h2",{className:"text-2xl font-bold text-center",children:"贊助牆"}),(0,a.jsx)("p",{className:"text-center text-muted-foreground text-sm",children:"感謝每一位支持我們的夥伴(完整贊助牆即將上線)"}),(0,a.jsx)("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-3 max-h-[320px] overflow-y-auto",children:e.map(e=>(0,a.jsxs)("div",{className:"rounded-lg border border-dashed bg-muted/30 p-4 text-center text-sm text-muted-foreground",children:[(0,a.jsx)("div",{className:"w-10 h-10 rounded-full bg-primary/10 mx-auto mb-2"}),e.name]},e.id))})]})}var R=s(6524);let T=[{q:"贊助金額用在哪裡?",a:"我們公開每月營運成本表(GCP、AI 工具、域名、金流等),贊助收入用於支撐這些支出,使平台能持續免費提供個人理財功能。請見本頁「營運成本透明表」。"},{q:"贊助和訂閱有什麼不同?",a:"所有個人理財功能已免費開放。贊助是純粹支持平台營運,不會解鎖額外功能或權限。"},{q:"可以取消每月贊助嗎?",a:"可以。登入後前往「設定 → 贊助管理」,即可取消定期贊助。"},{q:"最低贊助金額是多少?",a:"一次性或每月贊助最低 NT$200,也可選擇 200 / 600 / 800 / 1200 等預設方案。"},{q:"贊助牆是什麼?",a:"若您勾選「願意顯示於贊助牆」,我們會在贊助頁公開您的顯示名稱與留言(可選)。"},{q:"付款安全嗎?",a:"付款由綠界 ECPay 處理,本平台不儲存您的信用卡資訊。"}];function $(){return(0,a.jsxs)("section",{className:"space-y-4",children:[(0,a.jsx)("h2",{className:"text-2xl font-bold text-center",children:"常見問題"}),(0,a.jsx)(R.nD,{type:"single",collapsible:!0,className:"w-full max-w-2xl mx-auto",children:T.map((e,t)=>(0,a.jsxs)(R.As,{value:`faq-${t}`,children:[(0,a.jsx)(R.$m,{children:e.q}),(0,a.jsx)(R.ub,{className:"text-muted-foreground",children:e.a})]},e.q))})]})}
1var P=s(2962),D=s(61414),F=s(54306),_=s(9234);function V(e){return null===e?"待填":(0,N.C)(e,{showSymbol:!0})}function B(){var e;let{breakdown:t,loading:s}=function(){let[e,t]=(0,r.useState)(null),[s,a]=(0,r.useState)(!0);return(0,r.useEffect)(()=>{let e=!1;return(async()=>{try{let s=await fetch("/api/sponsor/cost-breakdown");if(!s.ok)throw Error("fetch failed");let a=await s.json();e||t(a)}catch(s){(0,S.vV)("useSponsorCostBreakdown failed:",s),e||t((0,_.sN)())}finally{e||a(!1)}})(),()=>{e=!0}},[]),{breakdown:e,loading:s}}();if(s||!t)return(0,a.jsx)("section",{id:"cost-breakdown",className:"scroll-mt-24 flex justify-center py-12",children:(0,a.jsx)(F.default,{})});let i=(e=t.items).some(e=>null===e.monthlyAmountTwd)?null:e.reduce((e,t)=>e+(t.monthlyAmountTwd??0),0);return(0,a.jsx)("section",{id:"cost-breakdown",className:"scroll-mt-24 space-y-4",children:(0,a.jsxs)(m.Zp,{className:"border-primary/15 shadow-sm",children:[(0,a.jsx)(m.aR,{className:"text-center sm:text-left",children:(0,a.jsxs)("div",{className:"flex flex-col sm:flex-row sm:items-center gap-3",children:[(0,a.jsx)("div",{className:"mx-auto sm:mx-0 flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10",children:(0,a.jsx)(D.A,{className:"h-5 w-5 text-primary","aria-hidden":!0})}),(0,a.jsxs)("div",{children:[(0,a.jsx)(m.ZB,{className:"text-2xl",children:"營運成本透明表"}),(0,a.jsxs)(m.BT,{className:"mt-1 max-w-2xl",children:["贊助收入用於支撐平台營運。以下為每月成本概估(年繳項目已換算月均),我們承諾",t.updateCadence,"並公開調整。"]})]})]})}),(0,a.jsxs)(m.Wu,{children:[(0,a.jsx)("div",{className:"rounded-lg border overflow-hidden",children:(0,a.jsxs)(P.XI,{children:[(0,a.jsx)(P.A0,{children:(0,a.jsxs)(P.Hj,{className:"bg-muted/40 hover:bg-muted/40",children:[(0,a.jsx)(P.nd,{className:"w-[120px] font-semibold",children:"項目"}),(0,a.jsx)(P.nd,{className:"font-semibold",children:"說明"}),(0,a.jsx)(P.nd,{className:"w-[140px] text-right font-semibold",children:"月均(NT$)"})]})}),(0,a.jsx)(P.BF,{children:t.items.map(e=>(0,a.jsxs)(P.Hj,{children:[(0,a.jsx)(P.nA,{className:"font-medium",children:e.label}),(0,a.jsx)(P.nA,{className:"text-muted-foreground",children:e.description}),(0,a.jsxs)(P.nA,{className:"text-right tabular-nums",children:[V(e.monthlyAmountTwd),"yearly"===e.billingPeriod&&null!==e.monthlyAmountTwd&&(0,a.jsxs)("p",{className:"text-xs text-muted-foreground font-normal",children:["年繳 ",V(e.amountTwd)," \xf7 12"]})]})]},e.id))}),(0,a.jsx)(P.Gg,{children:(0,a.jsxs)(P.Hj,{className:"bg-muted/30 hover:bg-muted/30",children:[(0,a.jsx)(P.nA,{colSpan:2,className:"font-semibold",children:"月合計"}),(0,a.jsx)(P.nA,{className:"text-right font-semibold tabular-nums",children:V(i)})]})})]})}),(0,a.jsxs)("p",{className:"mt-4 text-xs text-muted-foreground text-center sm:text-left",children:["最後更新:",t.lastUpdated.replace(/-/g,"/"),null===i?" \xb7 各項金額確認中":""]})]})]})})}var L=s(38187),z=s(32898),O=s(24571),U=s(76458),M=s(27703);let W={pending:"待付款",active:"進行中",completed:"已完成",cancelled:"已取消",failed:"失敗"};function Z(){let{user:e}=(0,p.A)(),{toast:t}=(0,x.dj)(),{sponsorships:s,loading:i,refresh:c}=function(){let{user:e}=(0,p.A)(),[t,s]=(0,r.useState)([]),[a,i]=(0,r.useState)(!0),l=(0,r.useCallback)(async()=>{if(!e||!U.db){s([]),i(!1);return}i(!0);try{let t=(0,O.P)((0,O.rJ)(U.db,M.I.sponsorships),(0,O._M)("userId","==",e.uid)),a=(await (0,O.GG)(t)).docs.map(e=>({id:e.id,...e.data()})).sort((e,t)=>{let s=e.createdAt?.seconds??0;return(t.createdAt?.seconds??0)-s});s(a)}catch(e){(0,S.vV)("useUserSponsorships failed:",e),s([])}finally{i(!1)}},[e]);return(0,r.useEffect)(()=>
1{l()},[l]),{sponsorships:t,loading:a,refresh:l}}(),[d,o]=(0,r.useState)(null),u=async s=>{if(e){o(s);try{let a=await e.getIdToken(),r=await fetch("/api/sponsorship/cancel",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({sponsorshipId:s})}),i=await r.json().catch(()=>({}));if(!r.ok)throw Error(i.error||"取消失敗");t({title:"已取消贊助"}),await c()}catch(e){t({variant:"destructive",title:"取消失敗",description:e instanceof Error?e.message:"請稍後再試"})}finally{o(null)}}};return i?(0,a.jsx)("div",{className:"flex justify-center py-12",children:(0,a.jsx)(h.A,{className:"h-8 w-8 animate-spin text-muted-foreground"})}):(0,a.jsxs)("div",{className:"space-y-6",children:[(0,a.jsxs)("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4",children:[(0,a.jsxs)("div",{children:[(0,a.jsxs)("h2",{className:"text-xl font-semibold flex items-center gap-2",children:[(0,a.jsx)(k.A,{className:"h-5 w-5 text-red-500"}),"贊助管理"]}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground mt-1",children:"查看您的贊助紀錄,或前往贊助頁支持我們"})]}),(0,a.jsx)(n.$,{asChild:!0,variant:"outline",children:(0,a.jsx)(l(),{href:"/sponsor",children:"前往贊助"})})]}),0===s.length?(0,a.jsx)(m.Zp,{children:(0,a.jsx)(m.Wu,{className:"py-10 text-center text-muted-foreground",children:"尚無贊助紀錄"})}):(0,a.jsx)("div",{className:"space-y-3",children:s.map(e=>(0,a.jsxs)(m.Zp,{children:[(0,a.jsxs)(m.aR,{className:"pb-2",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,a.jsxs)(m.ZB,{className:"text-base",children:["monthly"===e.type?"每月贊助":"一次性贊助"," ",(0,N.C)(e.amount,{showSymbol:!0})]}),(0,a.jsx)(L.E,{variant:"active"===e.status?"default":"secondary",children:W[e.status]??e.status})]}),(0,a.jsx)(m.BT,{children:e.merchantTradeNo?`訂單 ${e.merchantTradeNo.slice(0,12)}…`:""})]}),(0,a.jsxs)(m.Wu,{className:"space-y-3",children:["monthly"===e.type&&"active"===e.status&&e.renewalFailure&&(0,a.jsxs)("p",{className:"text-sm text-destructive",children:["最近一期扣款未成功(連續 ",e.renewalFailure.consecutiveFailures," 次)。若信用卡已更換或過期,請取消後重新設定每月贊助。"]}),"monthly"===e.type&&"active"===e.status&&(0,a.jsxs)(n.$,{variant:"outline",size:"sm",disabled:d===e.id,onClick:()=>u(e.id),children:[d===e.id?(0,a.jsx)(h.A,{className:"h-4 w-4 animate-spin mr-1"}):(0,a.jsx)(z.A,{className:"h-4 w-4 mr-1"}),"取消定期贊助"]})]})]},e.id))})]})}var H=s(25646);function J(){let{hasBetaAccess:e,loading:t}=function(){let{user:e}=(0,p.A)(),[t,s]=(0,r.useState)(!1),[a,i]=(0,r.useState)(!0);return(0,r.useEffect)(()=>{if(j.Wm.globalEnabled){s(!0),i(!1);return}if(!e||!U.db){s(!1),i(!1);return}let t=!1;return(async()=>{try{let a=(await (0,O.getDoc)((0,O.doc)(U.db,"users",e.uid))).data();t||s(a?.betaAccess===!0)}catch(e){(0,S.vV)("useBetaAccess failed:",e),t||s(!1)}finally{t||i(!1)}})(),()=>{t=!0}},[e]),{hasBetaAccess:t,loading:a}}();if(t)return null;let s=[j.Wm.aiAssistantV2,j.Wm.advancedReports].filter(e=>e.enabled);return(0,a.jsxs)(m.Zp,{className:"border-dashed",children:[(0,a.jsxs)(m.aR,{children:[(0,a.jsxs)(m.ZB,{className:"flex items-center gap-2 text-lg",children:[(0,a.jsx)(H.A,{className:"h-5 w-5"}),"Beta 功能",e&&(0,a.jsx)(L.E,{variant:"secondary",children:"已啟用"})]}),(0,a.jsx)(m.BT,{children:"搶先體驗實驗性功能。Beta 功能可能不穩定,隨時可能調整或移除。"})]}),(0,a.jsx)(m.Wu,{children:e?(0,a.jsxs)("ul",{className:"space-y-2 text-sm text-muted-foreground",children:[s.map(e=>(0,a.jsxs)("li",{children:["• ",e.label]},e.label)),0===s.length&&(0,a.jsx)("p",{children:"目前無開放中的 Beta 功能"})]}):(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"Beta 功能尚未對您的帳號開放。贊助者可優先取得 Beta 資格(即將推出)。"})})]})}},17956:(e,t,s)=>{s.d(t,{R:()=>r});var a=s(18654);class r{supportsRedirect(){return!1}createSuccessResult(e,t){return{success:!0,user:e,credential:t}}createErrorResult(e,t,s){return{success:!1,error:{code:e,message:t,originalError:s}}}handleAuthError(e){let t=e?.code||"auth/unknown-error",s=e?.message||"認證失敗,請稍後再試",r=e&&"object"==typeof e&&Object.keys(e).length>0?{code:t,message:s,error:e}:{code:t,message:s};(0,a.vV)(`[${this.name}] 認證錯誤:`,r);let i={"auth/user-not-found":"找不到此用戶,請先註冊","auth/wrong-password":"密碼不正確","auth/invalid-email":"電子郵件格式不正確","auth/user-disabled":"此帳戶已被停用","auth/email-already-in-use":"此電子郵件已被使用","auth/weak-password":"密碼強度不足","auth/operation-not-allowed":"此登å
1…¥æ–¹å¼æœªå•Ÿç”¨","auth/too-many-requests":"嘗試過多,請稍後再試","auth/network-request-failed":"網路連線失敗,請檢查網路","auth/invalid-credential":"認證資料無效","auth/popup-closed-by-user":"登入視窗被關閉","auth/popup-blocked":"彈出視窗被瀏覽器阻擋","auth/cancelled-popup-request":"登入請求已取消","auth/account-exists-with-different-credential":"此帳戶已使用其他登入方式註冊","auth/email-required":"需要 Email 權限才能完成登入","auth/config-error":"認證配置錯誤,請聯繫管理員","auth/configuration-not-found":"認證配置未找到,請確認 Firebase Console 設定","auth/no-redirect-result":"沒有重定向結果,請重新嘗試登入","auth/wrong-provider":"認證提供者不匹配","auth/not-initialized":"Firebase Auth 尚未初始化","auth/auto-login-failed":"自動登入失敗,請重新嘗試登入","auth/invalid-request":"請求參數錯誤","auth/access-denied":"用戶取消了授權","auth/unsupported-response-type":"不支援的回應類型","auth/invalid-scope":"無效的 scope 設定","auth/server-error":"伺服器錯誤,請稍後再試","auth/login-required":"需要登入","auth/interaction-required":"需要用戶互動","auth/line-error":"LINE Login 錯誤","auth/network-error":"網路連線錯誤"}[t]||s;return this.createErrorResult(t,i,e)}validateEmail(e){return!!e&&"string"==typeof e&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.trim())}normalizeEmail(e){return e.trim().toLowerCase()}validatePassword(e){return!e||e.length<8?{valid:!1,message:"密碼需至少 8 碼"}:/[A-Z]/.test(e)?/[a-z]/.test(e)?/[0-9]/.test(e)?/[^A-Za-z0-9]/.test(e)?{valid:!0}:{valid:!1,message:"密碼需包含至少一個特殊字元"}:{valid:!1,message:"密碼需包含至少一個數字"}:{valid:!1,message:"密碼需包含至少一個小寫字母"}:{valid:!1,message:"密碼需包含至少一個大寫字母"}}}},42457:(e,t,s)=>{s.d(t,{By:()=>i,iq:()=>n,wb:()=>r,x2:()=>l});let a="pendingReferralCode";function r(e){return e?e.trim().split(/\s+/)[0]??"":""}function i(e){let t=r(e);if(!t)return"";try{sessionStorage.setItem(a,t)}catch{}return t}function l(){try{return r(sessionStorage.getItem(a))}catch{return""}}function n(){let e=l();if(!e)return e;try{sessionStorage.removeItem(a)}catch{}return e}},57663:(e,t,s)=>{s.d(t,{E:()=>l});var a=s(85047),r=s(31615),i=s(34961);let l=r.forwardRef(({className:e,...t},s)=>(0,a.jsx)("div",{ref:s,className:(0,i.cn)("animate-pulse rounded-md bg-muted",e),...t}));l.displayName="Skeleton"},57670:(e,t,s)=>{s.d(t,{A:()=>u});var a=s(85047),r=s(31615),i=s(83139),l=s(68341),n=s(76842),c=s(82520),d=s(21410),o=s(41178);function u(){let{toast:e}=(0,o.dj)(),[t,s]=(0,r.useState)(!1),u=(0,r.useMemo)(()=>`${window.location.origin}/api/mcp`,[]),m=async()=>{try{await navigator.clipboard.writeText(u),s(!0),e({title:"已複製 MCP URL"}),setTimeout(()=>s(!1),2e3)}catch{e({title:"複製失敗",variant:"destructive"})}};return(0,a.jsxs)(c.Zp,{children:[(0,a.jsxs)(c.aR,{children:[(0,a.jsxs)(c.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(i.A,{className:"h-5 w-5"}),"連接 MCP(AI 助理)"]}),(0,a.jsx)(c.BT,{children:"無需在本站設定頁建立連線。只要在支援 OAuth 的 AI 客戶端新增遠端 MCP,並在瀏覽器完成登入與授權即可。"})]}),(0,a.jsxs)(c.Wu,{className:"space-y-4 text-sm",children:[(0,a.jsxs)("div",{className:"flex flex-wrap items-center gap-2 rounded-md border bg-muted/30 p-3",children:[(0,a.jsx)("code",{className:"break-all text-xs",children:u}),(0,a.jsxs)(d.$,{type:"button",size:"sm",variant:"outline",onClick:m,children:[t?(0,a.jsx)(l.A,{className:"mr-1 h-3 w-3"}):(0,a.jsx)(n.A,{className:"mr-1 h-3 w-3"}),"複製 URL"]})]}),(0,a.jsxs)("ol",{className:"list-decimal space-y-2 pl-5 text-muted-foreground",children:[(0,a.jsx)("li",{children:"在 AI 客戶端(例如 Claude 自訂 connector)新增 MCP,URL 貼上上方網址;若要求 OAuth,Client ID 由服務方提供(非您的帳號 UID)。"}),(0,a.jsx)("li",{children:"儲存後由客戶端發起連線,瀏覽器會開啟鑫世紀理財登å
1…¥èˆ‡æŽˆæ¬Šé ã€‚"}),(0,a.jsx)("li",{children:"登入並按「允許並繼續」後,會自動回到 AI 客戶端,即可使用試算與財務摘要工具。"})]}),(0,a.jsxs)("p",{className:"text-xs text-muted-foreground",children:["連線名稱建議:",(0,a.jsx)("span",{className:"font-mono",children:"xynergy-finance-tools"}),"。過期或中斷時,在 AI 客戶端重新連線並再次完成瀏覽器授權即可。"]})]})]})}},70861:(e,t,s)=>{s.d(t,{WV:()=>d,i9:()=>p,p:()=>o,sm:()=>h,uz:()=>x});var a=s(30274),r=s(76458),i=s(17956),l=s(18654),n=s(32407);let c="apple.com";function d(){return"true"===n.env.NEXT_PUBLIC_ENABLE_APPLE_SIGNIN}function o(e){return!!e?.providerData.some(e=>e.providerId===c)}function u(){let e=new a.OAuthProvider(c);return e.addScope("email"),e.addScope("name"),e.setCustomParameters({locale:"zh_TW"}),e}class m extends i.R{type="apple";name="Apple";supportsRedirect(){return!1}async authenticate(e){if(!r.auth)return this.createErrorResult("auth/not-initialized","Firebase Auth 尚未初始化");try{let e=await (0,a.signInWithPopup)(r.auth,u());return(0,l.fH)("Apple 登入成功 (Popup):",e.user.uid),this.createSuccessResult(e.user,e)}catch(e){if("auth/popup-closed-by-user"===e.code)return this.createErrorResult("auth/popup-closed-by-user","登入視窗被關閉,請重試");if("auth/popup-blocked"===e.code)return this.createErrorResult("auth/popup-blocked","彈出視窗被瀏覽器阻擋,請允許彈出視窗後重試");if("auth/network-request-failed"===e.code)return this.createErrorResult("auth/network-request-failed","網路連線失敗,請檢查網路連線後重試");if("auth/account-exists-with-different-credential"===e.code)return this.createErrorResult("auth/account-exists-with-different-credential","æ­¤ Email 已使用其他登入方式註冊,請用原登入方式登入後,到「設定 › 帳號連結」連結 Apple");return this.handleAuthError(e)}}async handleRedirectResult(){return{success:!1,error:{code:"auth/no-redirect-result",message:"Apple 登入不使用重定向"}}}}let h=new m;async function x(){if(!r.auth?.currentUser)throw Error("使用者未登入");try{return await (0,a.linkWithPopup)(r.auth.currentUser,u())}catch(e){throw(0,l.vV)("連結 Apple 帳戶失敗:",e),e}}async function p(e){if(!r.auth)throw Error("Firebase Auth 尚未初始化");let t=await (0,a.reauthenticateWithPopup)(e,u()),s=a.OAuthProvider.credentialFromResult(t)?.accessToken;if(!s)return(0,l.vV)("Apple 重新驗證沒有回傳 access token"),!1;try{return await (0,a.revokeAccessToken)(r.auth,s),!0}catch(e){return(0,l.vV)("撤銷 Apple 授權失敗:",e),!1}}},83881:(e,t,s)=>{s.d(t,{sj:()=>d});var a=s(30274),r=s(76458),i=s(17956),l=s(18654),n=s(48716);class c extends i.R{type="facebook";name="Facebook";facebookProvider;constructor(){super(),this.facebookProvider=new a.FacebookAuthProvider,this.facebookProvider.addScope("email"),this.facebookProvider.addScope("public_profile")}supportsRedirect(){return!0}async authenticate(e){if(!r.auth)return this.createErrorResult("auth/not-initialized","Firebase Auth 尚未初始化");try{if(e?.redirect)return await this.signInWithRedirect(),{success:!0};let t=await (0,a.signInWithPopup)(r.auth,this.facebookProvider);return(0,l.fH)("Facebook 登入成功 (Popup):",t.user.email),this.createSuccessResult(t.user,t)}catch(e){if("auth/popup-closed-by-user"===e.code)return this.createErrorResult("auth/popup-closed-by-user","登入視窗被關閉,請重試");if("auth/popup-blocked"===e.code)return this.createErrorResult("auth/popup-blocked","彈出視窗被瀏覽器阻擋,請允許彈出視窗後重試");if("auth/network-request-failed"===e.code)return this.createErrorResult("auth/network-request-failed","網路連線失敗,請檢查網路連線後重試");if("auth/account-exists-with-different-credential"===e.code)return this.createErrorResult("auth/account-exists-with-different-credential","此帳戶已使用其他登入方式註冊,請使用原登入方式或連結帳戶");return this.handleAuthError(e)}}async handleRedirectResult(){if(!r.auth)return this.createErrorResult("auth/not-initialized","Firebase Auth 尚未初始化");try{let e=await (0,a.getRedirectResult)(r.auth);if(!e)return{success:!1,error:{code:"auth/no-redirect-result",message:"沒有重定向結果"}};if(!e.user?.providerData?.some(e=>"facebook.com"===e.providerId))return{success:!1,error:{code:"auth/wrong-provider",message:"不是 Facebook 登入"}};return(0,l.fH)("Facebook 登入成功 (Redirect):",e.user.email),this.createSuccessResult(e.user,e)}catch(e){return this.handleAuthError(e)}}async signInWithRedirect(){if(!r.auth)throw Error("Firebase Auth 尚未初始化");try{(0,n.setOAuthRedirectState)("facebook"),await (0,a.signInWithRedirect)(r.auth,this.facebookProvider)}
1catch(e){throw(0,l.vV)("Facebook 重定向登入失敗:",e),Error(`Facebook 登入失敗: ${e.message}`)}}}let d=new c},96803:(e,t,s)=>{s.r(t),s.d(t,{default:()=>sY});var a=s(85047),r=s(31615),i=s(46377),l=s(6386),n=s(56928),c=s(73289),d=s(82520),o=s(866),u=s(96968),m=s(99185),h=s(21410),x=s(97040),p=s(41178),f=s(73521),j=s(78308),v=s(63972),g=s(24571),y=s(76458),b=s(94164);s(69740);var w=s(30274),N=s(99922),k=s(18654),C=s(89088),A=s(18534),S=s(62557),E=s(10892),I=s(15418);let R=I.k5(["not_useful","too_complex","privacy_concerns","found_alternative","too_expensive","poor_support","other"]),T=I.k5(["interface","workflow","settings","features"]),$=I.k5(["free","under_100","100_300","300_500","500_1000","over_1000"]),P=I.k5(["free","premium","advisor"]),D=I.Ik({priorityFeatures:I.Yj().optional(),complexParts:I.YO(T).optional(),dataHandlingConcerns:I.Yj().optional(),expectedPrice:$.optional(),otherReason:I.Yj().min(10,"其他原因說明至少需要 10 個字").max(500,"其他原因說明不能超過 500 個字").optional()}),F=I.Ik({accounts:I.ai().int().min(0),transactions:I.ai().int().min(0),assets:I.ai().int().min(0),liabilities:I.ai().int().min(0),investments:I.ai().int().min(0),goals:I.ai().int().min(0),subscriptions:I.ai().int().min(0)}),_=I.Ik({accountAge:I.ai().int().min(0),subscriptionStatus:P,dataCounts:F,featureUsage:I.YO(I.Yj())}),V=I.Ik({userId:I.Yj().min(1,"用戶 ID 不能為空"),reasons:I.YO(R).min(1,"至少需要選擇一個刪除原因"),additionalFeedback:D,userStats:_}).refine(e=>!e.reasons.includes("other")||void 0!==e.additionalFeedback.otherReason&&e.additionalFeedback.otherReason.length>=10,{message:"選擇「其他」原因時,必須提供至少 10 個字的說明",path:["additionalFeedback","otherReason"]}).refine(e=>(e.reasons.includes("not_useful"),!0)).refine(e=>(e.reasons.includes("too_complex"),!0)).refine(e=>(e.reasons.includes("privacy_concerns"),!0)).refine(e=>(e.reasons.includes("too_expensive"),!0));var B=s(27703);async function L(e){if(!y.db)throw Error("Firestore 尚未初始化");try{let t=await (0,g.getDoc)((0,g.doc)(y.db,"users",e)),s=0;if(t.exists()){let e=t.data().createdAt;if(e){let t=e instanceof g.Timestamp?e.toDate():new Date(e),a=new Date,r=Math.abs(a.getTime()-t.getTime());s=Math.floor(r/864e5)}}let a="free";try{let t=(0,g.P)((0,g.rJ)(y.db,B.I.sponsorships),(0,g._M)("userId","==",e),(0,g._M)("status","==","active"));(await (0,g.GG)(t)).empty||(a="premium")}catch(e){(0,k.vV)("獲取贊助狀態失敗:",e)}let r={accounts:0,transactions:0,assets:0,liabilities:0,investments:0,goals:0,subscriptions:0};try{let[t,s,a,i,l,n,c]=await Promise.all([(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"accounts"),(0,g._M)("userId","==",e))),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"transactions"),(0,g._M)("userId","==",e))),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"assets"),(0,g._M)("userId","==",e))),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"liabilities"),(0,g._M)("userId","==",e))),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"investments"),(0,g._M)("userId","==",e))),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"goals"),(0,g._M)("userId","==",e))),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,B.I.sponsorships),(0,g._M)("userId","==",e)))]);r.accounts=t.size,r.transactions=s.size,r.assets=a.size,r.liabilities=i.size,r.investments=l.size,r.goals=n.size,r.subscriptions=c.size}catch(e){(0,k.vV)("統計資料數量失敗:",e)}let i=[];try{r.accounts>0&&i.push("accounts"),r.transactions>0&&i.push("transactions"),r.assets>0&&i.push("assets"),r.liabilities>0&&i.push("liabilities"),r.investments>0&&i.push("investments"),r.goals>0&&i.push("goals");let[t,s,a]=await Promise.all([(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"credit_cards"),(0,g._M)("userId","==",e))).catch(()=>null),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"insurancePolicies"),(0,g._M)("userId","==",e))).catch(()=>null),(0,g.GG)((0,g.P)((0,g.rJ)(y.db,"retirement_plans"),(0,g._M)("userId","==",e))).catch(()=>null)]);t&&t.size>0&&i.push("credit_cards"),s&&s.size>0&&i.push("insurance"),a&&a.size>0&&i.push("retirement")}catch(e){(0,k.vV)("分析功能使用情況失敗:",e)}return{accountAge:s,subscriptionStatus:a,dataCounts:r,featureUsage:i}}catch(e){return(0,k.vV)("獲取用戶統計資訊失敗:",e),{accountAge:0,subscriptionStatus:"free",dataCounts:{accounts:0,transactions:0,assets:0,liabilities:0,investments:0,goals:0,subscriptions:0},featureUsage:[]}}}async function z(e,t){if(!y.db)throw Error("Firestore 尚未初始化");try{let s=await L(e),a=new Set(["interface","workflow","settings","features"]),r=t.additionalFeedback.complexParts?.filter(e=>"string"==typeof e&&a.has(e)),i=new Set(["free","under_100","100_300","300_500","500_1000","over_1000"]),l=t.additionalFeedback.expectedPrice,n="string"==typeof l&&i.has(l)?l:void 0,c={userId:e,reasons:t.reasons,additionalFeedback:{...t.additionalFeedback,complexParts:r,expectedPrice:n},userStats:s},d=V.parse(c),o=Object.fromEntries(Object.entries(d.additionalFeedback).filter(([e,t])=>void 0!==t));
1return(await (0,g.gS)((0,g.rJ)(y.db,"account_deletion_feedback"),{...d,additionalFeedback:o,submittedAt:(0,g.serverTimestamp)()})).id}catch(e){if((0,k.vV)("儲存帳號刪除回饋失敗:",e),e?.issues){let t=e.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join(", ");throw Error(`問卷資料驗證失敗: ${t}`)}throw Error(e?.message||"儲存回饋資料失敗,請稍後再試")}}var O=s(70861);let U=[{value:"not_useful",label:"功能不符合需求"},{value:"too_complex",label:"使用太複雜"},{value:"privacy_concerns",label:"隱私疑慮"},{value:"found_alternative",label:"找到替代方案"},{value:"too_expensive",label:"價格太貴"},{value:"poor_support",label:"客服不佳"},{value:"other",label:"其他"}],M=[{value:"interface",label:"介面設計"},{value:"workflow",label:"操作流程"},{value:"settings",label:"功能設定"},{value:"features",label:"功能使用"}],W=[{value:"free",label:"免費"},{value:"under_100",label:"100 元以下"},{value:"100_300",label:"100-300 元"},{value:"300_500",label:"300-500 元"},{value:"500_1000",label:"500-1000 元"},{value:"over_1000",label:"1000 元以上"}];function Z({open:e,userId:t,onOpenChange:s}){let{toast:l}=(0,p.dj)(),n=(0,i.useRouter)(),[c,d]=(0,r.useState)([]),[o,x]=(0,r.useState)({}),[f,j]=(0,r.useState)({}),[v,g]=(0,r.useState)(!1),[b,w]=(0,r.useState)(null),N=(0,r.useRef)(!1);(0,r.useEffect)(()=>{e||(d([]),x({}),j({}),w(null))},[e]);let k=async()=>{let e=y.auth?.currentUser;if(N.current||!(0,O.WV)()||!(0,O.p)(e)||!e)return!0;try{let t=await (0,O.i9)(e);return N.current=!0,t||l({title:"無法撤銷 Apple 授權",description:"帳號仍會刪除;可到 Apple ID 設定的「使用 Apple 登入」自行移除本服務"}),!0}catch(e){return l({title:"已停止刪除",description:e?.code==="auth/popup-closed-by-user"||e?.code==="auth/cancelled-popup-request"?"需要再以 Apple 驗證一次才能刪除帳號":e?.message||"Apple 驗證失敗,請稍後再試",variant:"destructive"}),!1}},C=async()=>{let e;if(e={},0===c.length&&(e.reasons="請至少選擇一個刪除原因"),c.includes("other")&&(!o.otherReason||o.otherReason.trim().length<10?e.otherReason="選擇「其他」原因時,請提供至少 10 個字的說明":o.otherReason.length>500&&(e.otherReason="說明不能超過 500 個字")),j(e),0===Object.keys(e).length){g(!0),w(null);try{if(!await k())return;await z(t,{reasons:c,additionalFeedback:o}),n.push("/account-deleted")}catch(e){w(e?.message||"提交失敗,請稍後再試"),l({title:"提交失敗",description:e?.message||"請稍後再試",variant:"destructive"})}finally{g(!1)}}},I=async()=>{g(!0);try{if(!await k())return void g(!1);n.push("/account-deleted?skipped=true")}catch(e){l({title:"錯誤",description:e?.message||"請稍後再試",variant:"destructive"}),g(!1)}};return(0,a.jsx)(A.lG,{open:e,onOpenChange:e=>{e||v||(s(!1),l({title:"已取消刪除",description:"刪除帳號流程已取消"}))},children:(0,a.jsxs)(A.Cf,{className:"sm:max-w-[600px] max-h-[90vh] overflow-y-auto",children:[(0,a.jsxs)(A.c7,{children:[(0,a.jsx)(A.L3,{children:"帳號刪除回饋問卷"}),(0,a.jsx)(A.rr,{children:"為了幫助我們改進服務,請告訴我們您刪除帳號的原因。此問卷為必填項目。"})]}),(0,a.jsxs)("div",{className:"space-y-6 py-4",children:[(0,a.jsxs)("div",{className:"space-y-3",children:[(0,a.jsxs)(u.J,{className:"text-base font-semibold",children:["請選擇刪除原因 ",(0,a.jsx)("span",{className:"text-red-500",children:"*"})]}),(0,a.jsx)("div",{className:"space-y-2",children:U.map(e=>(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)(S.S,{id:e.value,checked:c.includes(e.value),onCheckedChange:t=>{var s;return s=e.value,void(!0===t?d([...c,s]):(d(c.filter(e=>e!==s)),"not_useful"===s?x({...o,priorityFeatures:void 0}):"too_complex"===s?x({...o,complexParts:void 0}):"privacy_concerns"===s?x({...o,dataHandlingConcerns:void 0}):"too_expensive"===s?x({...o,expectedPrice:void 0}):"other"===s&&x({...o,otherReason:void 0})),j({}),w(null))}}),(0,a.jsx)(u.J,{htmlFor:e.value,className:"text-sm font-normal cursor-pointer",children:e.label})]},e.value))}),f.reasons&&(0,a.jsx)("p",{className:"text-sm text-red-500",children:f.reasons})]}),c.includes("not_useful")&&(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"priorityFeatures",children:"請告訴我們您最希望新增哪些功能?"}),(0,a.jsx)(E.T,{id:"priorityFeatures",placeholder:"請描述您希望新增的功能...",value:o.priorityFeatures||"",onChange:e=>x({...o,priorityFeatures:e.target.value}),rows:3})]}),c.includes("too_complex")&&(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{children:"請選擇哪個部分太複雜?"}),(0,a.jsx)("div",{className:"space-y-2",children:M.map(e=>(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)(S.S,{id:e.value,checked:o.complexParts?.includes(e.value)||!1,onCheckedChange:t=>{let s=o.complexParts||[];t?x({...o,complexParts:[...s,e.value]}):x({...o,complexParts:s.filter(t=>t!==e.value)})}}),(0,a.jsx)(u.J,{htmlFor:e.value,className:"text-sm font-normal cursor-pointer",children:e.label})]},e.value))})]}),c.includes("privacy_concerns")&&(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"dataHandlingConcerns",children:"請告訴我們您對資料處理方式有哪些疑慮?"}),(0,a.jsx)(E.T,{id:"dataHandlingConcerns",placeholder:"請描述您的疑慮...",value:o.dataHandlingConcerns||"",onChange:e=>x({...o,dataHandlingConcerns:e.target.value}),rows:3})]}),c.includes("too_expensive")&&(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{children:"請選擇您期望的價格區間"}),(0,a.jsx)(m.z,{value:o.expectedPrice,onValueChange:e=>x({...o,expectedPrice:e}),children:W.map(e=>(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)(m.C,{value:e.value,id:e.value}),(0,a.jsx)(u.J,{htmlFor:e.value,className:"text-sm font-normal cursor-pointer",children:e.label})]},e.value))})]}),c.includes("other")&&(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)(u.J,{htmlFor:"otherReason",children:["請說明其他原因 ",(0,a.jsx)("span",{className:"text-red-500",children:"*"}),(0,a.jsx)("span",{className:"text-sm text-muted-foreground ml-2",children:"(至少 10 個字,最多 500 個字)"})]}),(0,a.jsx)(E.T,{id:"otherReason",placeholder:"請詳細說明您的刪除原因...",value:o.otherReason||"",onChange:e=>x({...o,otherReason:e.target.value}),rows:4,maxLength:500}),(0,a.jsxs)("div",{className:"flex justify-between text-xs text-muted-foreground",children:[(0,a.jsx)("span",{children:f.otherReason&&(0,a.jsx)("span",{className:"text-red-500",children:f.otherReason})}),(0,a.jsxs)("span",{children:[o.otherReason?.length||0," / 500"]})]})]}),b&&(0,a.jsx)("div",{className:"p-3 bg-red-50 dark:bg-red-950/20 border border-red-200 dark:border-red-800 rounded-md",children:(0,a.jsx)("p",{className:"text-sm text-red-600 dark:text-red-400",children:b})})]}),(0,a.jsx)(A.Es,{className:"flex-col sm:flex-row gap-2",children:b?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(h.$,{variant:"outline",onClick:I,disabled:v,children:"跳過問卷"}),(0,a.jsx)(h.$,{onClick:()=>{w(null),C()},disabled:v,children:v?"重試中...":"重試"})]}):(0,a.jsx)(h.$,{onClick:C,disabled:v||0===c.length,children:v?"提交中...":"提交問卷"})})]})})}var H=s(14560),J=s(79579),G=s(36506),Y=s(35346),q=s(26787),X=s(54938),K=s(19548),Q=s(83474),ee=s(52204),et=s(28723);function es(){let{user:e}=(0,f.A)(),{toast:t}=(0,p.dj)(),[s,i]=(0,r.useState)(!0),[l,n]=(0,r.useState)(!1),[c,d]=(0,r.useState)(!1),[o,u]=(0,r.useState)(5),[m,h]=(0,r.useState)(""),x=(0,r.useCallback)(async()=>
1{if(!e)return void i(!1);i(!0);try{let t=await e.getIdToken(),s=await (0,ee._D)(t);s.submitted&&s.review?(d(!0),u(s.review.rating),h(s.review.comment)):(d(!1),u(5),h(""))}catch(s){let e=s instanceof Error?s:Error(String(s));K.Cp(e,{tags:{source:"PlatformReviewSettingsSection.load"}}),t({variant:"destructive",title:"載入失敗",description:e.message})}finally{i(!1)}},[e,t]);(0,r.useEffect)(()=>{x()},[x]);let j=async()=>{if(e){n(!0);try{let s=await e.getIdToken(),a={rating:o,comment:m.trim()};c?(await (0,ee.nX)(s,a),t({title:"已更新",description:"您的好評已儲存"})):(await (0,ee.yO)(s,a),await (0,et.tD)(e.uid),d(!0),t({title:"感謝您的回饋!"})),await x()}catch(s){let e=s instanceof Error?s:Error(String(s));K.Cp(e,{tags:{source:"PlatformReviewSettingsSection.save"}}),t({variant:"destructive",title:"儲存失敗",description:e.message})}finally{n(!1)}}};return(0,a.jsxs)("div",{className:"mt-8 border-t pt-6",children:[(0,a.jsx)("p",{className:"text-sm text-muted-foreground mb-3",children:"我的好評 \xb7 每位用戶一則,可隨時修改"}),s?(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"載入中…"}):(0,a.jsx)(Q.m,{rating:o,onRatingChange:u,comment:m,onCommentChange:h,onSubmit:j,submitting:l,submitLabel:c?"更新":"送出",commentId:"settings-platform-review-comment"})]})}var ea=s(18977),er=s(31862);function ei(){let{toast:e}=(0,p.dj)(),{user:t}=(0,f.A)(),{theme:s}=(0,N.D)(),l=(0,n.mN)({resolver:(0,c.u)(X.Fx),defaultValues:{name:"",email:"",birthday:"",gender:""}}),[S,E]=(0,r.useState)("");(0,i.useRouter)();let[I,R]=(0,r.useState)(!!t?.emailVerified),[T,$]=(0,r.useState)(!1),[P,D]=(0,r.useState)(!1),[F,_]=(0,r.useState)(!1),[V,B]=(0,r.useState)(!1),[L,z]=(0,r.useState)(!1),[O,U]=(0,r.useState)(null),[M,W]=(0,r.useState)(null),[K,Q]=(0,r.useState)(!1),et=(0,r.useRef)(null),ei=(0,r.useRef)(!1),el=(0,r.useRef)(null);(0,r.useEffect)(()=>{if(!t)return;if(!y.db)return void e({title:"Firebase 尚未初始化",description:"請檢查 .env 設定與 firebase.ts 初始化流程。",variant:"destructive"});(0,k.fH)("開始監聽用戶資料變更...");let s=(0,g.aQ)((0,g.doc)(y.db,"users",t.uid),e=>{if(e.exists()){let s=e.data(),a=JSON.stringify({name:s.name||s.profile?.name||"",email:s.email||s.profile?.email||"",birthday:s.birthday||s.profile?.birthDate||"",gender:s.gender??"",emailVerified:s.emailVerified});if(et.current===a||ei.current)return;et.current=a,W((0,ea.xK)(s));let r={name:s.name||s.profile?.name||"",email:s.email||s.profile?.email||"",birthday:s.birthday||s.profile?.birthDate||"",gender:"male"===s.gender||"female"===s.gender?s.gender:""};l.reset(r),E(r.email||"");let i=!1;s.hasOwnProperty("emailVerified")?(i=!0===s.emailVerified,(0,k.fH)("使用 Firestore emailVerified 狀態:",i)):(i=t.emailVerified,(0,k.fH)("使用 Auth emailVerified 狀態並同步到 Firestore:",i),ei.current=!0,(async()=>{try{await (0,g.mZ)((0,g.doc)(y.db,"users",t.uid),{emailVerified:t.emailVerified,updatedAt:new Date}),(0,k.fH)("已同步 emailVerified 到 Firestore:",t.emailVerified),setTimeout(()=>{ei.current=!1},100)}catch(e){(0,k.vV)("同步 emailVerified 到 Firestore 失敗:",e),ei.current=!1}})()),(0,k.fH)("最終 emailVerified 狀態:",i),R(i)}},e=>{(0,k.vV)("監聽用戶資料失敗:",e)});return(async()=>{try{(0,k.fH)("初始同步 Auth 狀態..."),await (0,w.reload)(t),(0,k.fH)("Auth emailVerified 原始值:",t.emailVerified);let e=await (0,g.getDoc)((0,g.doc)(y.db,"users",t.uid));if(e.exists()){let s=e.data(),a=!1;if(s.hasOwnProperty("emailVerified"))a=!0===s.emailVerified,(0,k.fH)("初始同步:使用 Firestore emailVerified 狀態:",a);else{a=t.emailVerified,(0,k.fH)("初始同步:使用 Auth emailVerified 狀態並同步到 Firestore:",a);try{await (0,g.mZ)((0,g.doc)(y.db,"users",t.uid),{emailVerified:t.emailVerified,updatedAt:new Date}),(0,k.fH)("初始同步:已同步 emailVerified 到 Firestore:",t.emailVerified)}catch(e){(0,k.vV)("初始同步:同步 emailVerified 到 Firestore 失敗:",e)}}(0,k.fH)("初始同步:最終 emailVerified 狀態:",a),R(a)}}catch(e){(0,k.vV)("初始同步 Auth 狀態失敗:",e)}})(),()=>{(0,k.fH)("清理用戶資料監聽器"),s()}},[t,e]);let{update:en}
1=(0,b.s)(t?.uid);(0,r.useEffect)(()=>{t?.uid&&(async()=>{let e=await (0,q.Sk)(t.uid);e&&U(e)})()},[t?.uid]);let ec=async()=>{if(!t||!y.db)return;let s=(0,Y.SD)();l.setValue("name",s);try{await (0,g.mZ)((0,g.doc)(y.db,"users",t.uid),{name:s,updatedAt:new Date});try{await (0,w.updateProfile)(t,{displayName:s})}catch(e){(0,k.vV)("同步 Auth displayName 失敗",e)}let e=await t.getIdToken();await (0,ee.b2)(e)}catch(t){(0,k.vV)("更新名稱失敗:",t),e({title:"更新失敗",description:"無法更新名稱,請稍後再試",variant:"destructive"})}},ed=async e=>{if(U(e),t){(0,er.clearUserAvatarCached)(t.uid);try{let e=await t.getIdToken();await (0,ee.b2)(e)}catch(e){(0,k.vV)("同步好評顯示失敗",e)}}},eo=async s=>{if(t){if(!y.db)return void e({title:"Firebase 尚未初始化",description:"請檢查 .env 設定與 firebase.ts 初始化流程。",variant:"destructive"});if(t.email&&!t.emailVerified)return void e({title:"尚未完成信箱驗證",description:"請先驗證電子郵件後再更新敏感資料。",variant:"destructive"});try{let a=s.name?.trim()??"";if(await en({name:a,email:s.email,birthday:s.birthday,gender:s.gender||void 0}),a&&a!==(t.displayName??""))try{await (0,w.updateProfile)(t,{displayName:a})}catch(e){(0,k.vV)("同步 Auth displayName 失敗",e)}await (0,C.BS)(t.uid);let r=await t.getIdToken();await (0,ee.b2)(r),e({title:"個人資料已更新",description:"您的個人資料已成功更新。"})}catch(t){e({title:"更新失敗",description:"請稍後再試。",variant:"destructive"})}}},eu=async()=>{(0,k.fH)("按鈕被點擊,開始處理...");try{(0,k.fH)("嘗試顯示 toast..."),e({title:"測試",description:"Toast 測試訊息"}),(0,k.fH)("Toast 已調用")}catch(e){(0,k.vV)("Toast 錯誤:",e)}if(!t){(0,k.fH)("用戶未登入"),e({title:"錯誤",description:"用戶未登入",variant:"destructive"});return}$(!0),e({title:"處理中",description:"正在準備寄送驗證信..."});try{if((0,k.fH)("開始寄送驗證信..."),(0,k.fH)("用戶狀態:",{uid:t.uid,email:t.email,emailVerified:t.emailVerified,isAnonymous:t.isAnonymous}),(0,k.fH)("重新載入用戶狀態..."),await (0,w.reload)(t),(0,k.fH)("重新載入後的用戶狀態:",{uid:t.uid,email:t.email,emailVerified:t.emailVerified,isAnonymous:t.isAnonymous}),t.isAnonymous)return void e({title:"寄送失敗",description:"匿名用戶無法寄送驗證信",variant:"destructive"});let s=(l.getValues("email")||"").trim();if(!s)return void e({title:"寄送失敗",description:"請先輸入電子郵件地址",variant:"destructive"});t.email&&t.email.toLowerCase()===s.toLowerCase()?(await (0,w.sendEmailVerification)(t,{url:`${window.location.origin}/auth?verified=true`,handleCodeInApp:!1}),e({title:"✅ 驗證信已寄出",description:"請檢查您的信箱(包括垃圾郵件)。"})):(await (0,w.verifyBeforeUpdateEmail)(t,s,{url:`${window.location.origin}/auth?verified=true`,handleCodeInApp:!1}),e({title:"✅ 驗證信已寄出",description:"請前往新信箱完成驗證。"}))}catch(t){(0,k.vV)("寄送驗證信失敗:",t),(0,k.vV)("錯誤代碼:",t.code),(0,k.vV)("錯誤訊息:",t.message),"auth/too-many-requests"===t.code?e({title:"寄送失敗",description:"請求過於頻繁,請稍後再試。",variant:"destructive"}):"auth/user-not-found"===t.code?e({title:"寄送失敗",description:"用戶不存在,請重新登入。",variant:"destructive"}):"auth/requires-recent-login"===t.code?e({title:"寄送失敗",description:"需要重新登入以進行此操作",variant:"destructive"}):"auth/operation-not-allowed"===t.code?e({title:"寄送失敗",description:"此操作不被允許,請聯繫客服",variant:"destructive"}):"auth/network-request-failed"===t.code?e({title:"寄送失敗",description:"網路連線失敗,請檢查網路連線",variant:"destructive"}):e({title:"寄送失敗",description:`錯誤: ${t.message||"請稍後再試"}`,variant:"destructive"})}finally{$(!1)}};return(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(j.A,{className:"h-5 w-5"}),"個人資料"]}),(0,a.jsx)(d.BT,{children:"更新您的個人資料和聯絡資訊"})]}),(0,a.jsxs)(d.Wu,{children:[(0,a.jsxs)("div",{className:"mb-6 pb-6 border-b space-y-4",children:[(0,a.jsxs)("div",{className:"flex flex-col items-center gap-2",children:[(0,a.jsx)("div",{className:"cursor-pointer hover:opacity-80 transition-opacity",onClick:()=>z(!0),children:(0,a.jsx)(J.H,{userId:t?.uid,size:"large"})}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"點擊頭像可編輯虛擬外觀"}),(0,a.jsx)(h.$,{type:"button",variant:"outline",size:"sm",className:"rounded-xl",onClick:()=>z(!0),children:"編輯虛擬頭像"})]}),t?(0,a.jsx)(G._,{userId:t.uid,currentPhotoUrl:M,oauthPhotoUrl:t.photoURL,getToken:()=>t.getIdToken(),onPhotoChange:async e=>{if(y.db){await (0,g.mZ)((0,g.doc)(y.db,"users",t.uid),{photoURL:e,updatedAt:new Date}),W(e),(0,er.clearUserAvatarCached)(t.uid);try{let e=await t.getIdToken();await (0,ee.b2)(e)}catch(e){(0,k.vV)("同步好評顯示失敗",e)}}}}):null]}),(0,a.jsx)(x.lV,{...l,children:(0,a.jsxs)("form",{onSubmit:l.handleSubmit(eo),className:"space-y-4",children:[(0,a.jsxs)("div",{className:"grid gap-4 md:grid-cols-2",children:[(0,a.jsx)(x.zB,{control:l.control,name:"name",render:({field:e})=>(0,a.jsxs)(x.eI,{children:[(0,a.jsx)(x.lR,{children:"暱稱"}),(0,a.jsxs)("div",{className:"relative flex gap-2",children:[(0,a.jsx)(x.MJ,{children:(0,a.jsx)(o.p,{placeholder:"請輸入暱稱",className:"flex-1",...e})}),(0,a.jsx)(h.$,{type:"button",variant:"outline",size:"icon",onClick:ec,title:"生成隨機名稱",children:(0,a.jsx)(v.A,{className:"h-4 w-4"})})]}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"點擊 ✨ 按鈕可自動生成隨機名稱"}),(0,a.jsx)(x.C5,{})]})}),(0,a.jsx)(x.zB,{control:l.control,name:"email",render:({field:e})=>(0,a.jsxs)(x.eI,{children:[(0,a.jsx)(x.lR,{children:"電子郵件"}),(0,a.jsx)(x.MJ,{children:(0,a.jsx)(o.p,{type:"email",autoComplete:"email",placeholder:"請輸入電子郵件地址",...e})}),(0,a.jsx)("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:e.value&&""!==e.value.trim()?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("span",{className:`${I?"text-green-500":"text-yellow-600 dark:text-yellow-500"}`,children:I?"已驗證":"未驗證"}),!I&&(0,a.jsx)(h.$,{variant:"outline",size:"sm",onClick:eu,disabled:T,children:T?"寄送中...":"寄送驗證信"})]}):(0,a.jsx)("span",{className:"text-blue-500",children:"未設定電子郵件"})}),(0,a.jsx)(x.C5,{})]})}),(0,a.jsx)(x.zB,{control:l.control,name:"birthday",render:({field:e})=>(0,a.jsxs)(x.eI,{children:[(0,a.jsx)(x.lR,{children:"生日"}),(0,a.jsx)("div",{className:"relative z-10 cursor-pointer",onClick:()=>el.current?.showPicker?.(),children:(0,a.jsx)("input",{ref:el,type:"date",value:function(e){if(!e)return"";if(/^\d{4}-\d{2}-\d{2}$/.test(e))return e;let t=new Date(e);return isNaN(t.getTime())?"":t.toISOString().slice(0,10)}(e.value),onChange:t=>e.onChange(t.target.value),onBlur:e.onBlur,name:e.name,className:"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm font-normal shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer"})}),(0,a.jsx)(x.C5,{})]})}),(0,a.jsx)(x.zB,{control:l.control,name:"gender",render:({field:e})=>(0,a.jsxs)(x.eI,{children:[(0,a.jsx)(x.lR,{children:"性別"}),(0,a.jsx)(x.MJ,{children:(0,a.jsxs)(m.z,{value:e.value??"",onValueChange:t=>e.onChange("male"===t||"female"===t?t:""),className:"flex gap-6",children:[(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)(m.C,{value:"male",id:"gender-male"}),(0,a.jsx)(u.J,{htmlFor:"gender-male",className:"font-normal cursor-pointer",children:"男性"})]}),(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)(m.C,{value:"female",id:"gender-female"}),(0,a.jsx)(u.J,{htmlFor:"gender-female",className:"font-normal cursor-pointer",children:"女性"})]})]})}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"供保險保費計算使用"}),(0,a.jsx)(x.C5,{})]})})]}),(0,a.jsx)("div",{className:"flex justify-end",children:(0,a.jsx)(h.$,{type:"submit",disabled:l.formState.isSubmitting,children:l.formState.isSubmitting?"更新中...":"更新個人資料"})})]})}),(0,a.jsx)(es,{}),(0,a.jsx)("div",{className:"mt-8 border-t pt-6",children:(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(h.$,{variant:"outline",className:"border-red-500 text-red-600 hover:bg-red-50 hover:text-red-700 dark:hover:bg-red-950/20 dark:text-red-400 dark:border-red-400 dark:hover:text-red-300",onClick:()=>D(!0),children:"刪除帳戶"}),(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"此操作將永久刪除您的所有資料且無法恢復"})]})}),(0,a.jsx)(A.lG,{open:P,onOpenChange:D,children:(0,a.jsxs)(A.Cf,{children:[(0,a.jsxs)(A.c7,{children:[(0,a.jsx)(A.L3,{children:"確認刪除帳戶?"}),(0,a.jsx)(A.rr,{children:"此操作無法復原,將會刪除所有您的資料與登入帳戶。"})]}),(0,a.jsxs)(A.Es,{children:[(0,a.jsx)(h.$,{variant:"outline",onClick:()=>D(!1),children:"取消"}),(0,a.jsx)(h.$,{variant:"destructive",disabled:K,onClick:()=>{D(!1),_(!0)},children:"確認刪除"})]})]})}),t&&(0,a.jsx)(Z,{open:F,userId:t.uid,onOpenChange:e=>{_(e),e||D(!1)}}),t&&(0,a.jsx)(H.V,{open:L,onOpenChange:z,userId:t.uid,initialConfig:O,onSave:ed})]})]})}var el=s(56620),en=s(17749),ec=s(76842),ed=s(51475),eo=s(42457);let eu=({src:e,alt:t,fallback:s,className:i})=>{let[l,n]=(0,r.useState)(!1);return(0,a.jsx)(el.default,{src:l?s:e,alt:t,width:20,height:20,className:i,unoptimized:!0,onError:()=>n(!0)})},em=({className:e})=>(0,a.jsx)(eu,{src:"/social-icons/facebook.png",alt:"Facebook",fallback:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%231877F2'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E",className:e}),eh=({className:e})=>(0,a.jsx)(eu,{src:"/social-icons/instagram.png",alt:"Instagram",fallback:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cdefs%3E%3ClinearGradient id='ig' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' stop-color='%23FCAF45'/%3E%3Cstop offset='50%25' stop-color='%23E1306C'/%3E%3Cstop offset='100%25' stop-color='%23833AB4'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect x='2' y='2' width='20' height='20' rx='5' fill='url(%23ig)'/%3E%3Ccircle cx='12' cy='12' r='4' fill='white'/%3E%3Ccircle cx='17.5' cy='6.5' r='1' fill='white'/%3E%3C/svg%3E",className:e}),ex=({className:e})=>(0,a.jsx)(eu,{src:"/social-icons/threads.png",alt:"Threads",fallback:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z'/%3E%3C/svg%3E",className:e}),ep=({className:e})=>(0,a.jsx)(eu,{src:"/social-icons/x.png",alt:"X (Twitter)",fallback:"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231z'/%3E%3C/svg%3E",className:e}),ef=({className:e})=>(0,a.jsx)(el.default,{src:"/social-icons/line.png",alt:"LINE",width:20,height:20,className:e,onError:e=>{e.currentTarget.src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%2300B900'%3E%3Cpath d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z'/%3E%3C/svg%3E"}});function ej(e,t){return`推薦你使用鑫世紀理財管理個人財務!
2
3註冊後在個人資料輸入我的推薦碼「${e}」,雙方即可獲得 XP 獎勵。
4
5立即註冊:${t}
6
7#財務規劃 #個人理財`}function ev(){let{user:e}=(0,f.A)(),{toast:t}=(0,p.dj)(),l=(0,i.useSearchParams)(),[n,c]=(0,r.useState)(""),[m,x]=(0,r.useState)(!1),[j,v]=(0,r.useState)(""),[b,w]=(0,r.useState)(!1),[N,k]=(0,r.useState)("");(0,r.useEffect)(()=>
7{if(!e?.uid||!y.db)return;let t=(0,g.aQ)((0,g.doc)(y.db,"users",e.uid),e=>{e.exists()&&c(e.data()?.referralCode||"")});return()=>t()},[e?.uid]),(0,r.useEffect)(()=>{let e=(0,eo.wb)(l.get("ref"));if(e){(0,eo.By)(e),v(e);return}let t=(0,eo.x2)();t&&v(t)},[l]);let C=(0,r.useMemo)(()=>{let e=window.location.origin;return{origin:e,buildUrl:t=>e?`${e}/auth?ref=${encodeURIComponent(t)}`:"/auth"}},[]),A=async e=>{try{await navigator.clipboard.writeText(e),t({title:"已複製到剪貼簿"})}catch{t({title:"複製失敗",description:"請手動複製",variant:"destructive"})}},S=(e,t)=>{let s=C.buildUrl(t),a=ej(t,s);if(!s)return null;switch(e){case"fb":return`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(s)}&quote=${encodeURIComponent(a)}`;case"x":return`https://twitter.com/intent/tweet?text=${encodeURIComponent(a)}&url=${encodeURIComponent(s)}`;case"threads":return`https://www.threads.net/intent/post?text=${encodeURIComponent(`${a}
8${s}`)}`;case"line":return`https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(s)}&text=${encodeURIComponent(a)}`;default:return null}},E=async e=>{let s=C.buildUrl(e),a=ej(e,s);if(/Android|iPhone|iPad|iPod/i.test(navigator.userAgent)&&"u">typeof navigator&&"function"==typeof navigator.share)try{await navigator.share({text:a,url:s}),t({title:"已開啟分享"});return}catch{}await A(a),t({title:"已複製分享文案",description:"Instagram 不支援網頁直接分享外部連結,請到 Instagram 應用程式貼上文案和連結"})},I=async e=>{if(e.preventDefault(),!j.trim())return void k("請輸入推薦碼");w(!0),k("");try{let{redeemReferralCode:e}=await Promise.all([s.e(5084),s.e(7327)]).then(s.bind(s,37327)),a=await e(j.trim());a.success?((0,eo.iq)(),t({title:"推薦碼綁定成功!",description:a.message||"推薦碼已成功綁定"}),v(""),k("")):k(a.message||"綁定失敗,請稍後再試")}catch(s){let e=s instanceof Error?s.message:"使用推薦碼失敗,請稍後再試";k(e),t({title:"推薦碼綁定失敗",description:e,variant:"destructive"})}finally{w(!1)}},R=n?n.split(" ")[0]:"";return(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(en.A,{className:"h-5 w-5"}),"推薦與分享"]})}),(0,a.jsxs)(d.Wu,{className:"space-y-6",children:[(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{children:"我的推薦碼"}),n?(0,a.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,a.jsx)("span",{className:"font-mono font-semibold",children:R}),(0,a.jsxs)(h.$,{size:"sm",variant:"outline",onClick:()=>{navigator.clipboard.writeText(R),x(!0),setTimeout(()=>x(!1),1500),t({title:"已複製推薦碼"})},children:[(0,a.jsx)(ec.A,{className:"h-4 w-4 mr-1"}),m?"已複製!":"複製推薦碼"]}),(0,a.jsxs)(h.$,{size:"sm",variant:"outline",onClick:()=>A(C.buildUrl(R)),children:[(0,a.jsx)(ed.A,{className:"h-4 w-4 mr-1"}),"複製連結"]})]}):(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"尚未產生推薦碼,請聯繫客服或於註冊後重新整理"})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"referralCodeBind",children:"使用推薦碼"}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)(o.p,{id:"referralCodeBind",value:j,onChange:e=>v(e.target.value),placeholder:"請輸入推薦碼,綁定成功後雙方可獲得 XP",disabled:b,className:"flex-1"}),(0,a.jsx)(h.$,{type:"button",onClick:I,disabled:b||!j.trim(),children:b?"驗證中...":"使用"})]}),N&&(0,a.jsx)("p",{className:`text-sm ${N.includes("成功")?"text-green-600":"text-red-600"}`,children:N})]}),(0,a.jsxs)("div",{className:"space-y-3",children:[(0,a.jsxs)("div",{className:"text-sm font-medium flex items-center gap-2",children:[(0,a.jsx)(en.A,{className:"h-4 w-4"}),"社群分享"]}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"分享到 FB / IG / Threads / X / LINE。IG 桌面版會複製文案與連結,請到應用程式貼上。"}),R?(0,a.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,a.jsx)("a",{href:S("fb",R)||"#",target:"_blank",rel:"noopener noreferrer",title:"分享到 Facebook",className:"inline-flex items-center justify-center transition-opacity hover:opacity-80",children:(0,a.jsx)(em,{className:"h-6 w-6"})}),(0,a.jsx)("a",{href:"#",onClick:e=>{e.preventDefault(),E(R)},title:"分享到 Instagram",className:"inline-flex items-center justify-center transition-opacity hover:opacity-80 curs
8or-pointer",children:(0,a.jsx)(eh,{className:"h-6 w-6"})}),(0,a.jsx)("a",{href:S("threads",R)||"#",target:"_blank",rel:"noopener noreferrer",title:"分享到 Threads",className:"inline-flex items-center justify-center transition-opacity hover:opacity-80",children:(0,a.jsx)(ex,{className:"h-6 w-6"})}),(0,a.jsx)("a",{href:S("x",R)||"#",target:"_blank",rel:"noopener noreferrer",title:"分享到 X (Twitter)",className:"inline-flex items-center justify-center transition-opacity hover:opacity-80",children:(0,a.jsx)(ep,{className:"h-6 w-6"})}),(0,a.jsx)("a",{href:S("line",R)||"#",target:"_blank",rel:"noopener noreferrer",title:"分享到 LINE",className:"inline-flex items-center justify-center transition-opacity hover:opacity-80",children:(0,a.jsx)(ef,{className:"h-6 w-6"})})]}):(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"請先取得推薦碼後再使用社群分享"})]})]})]})}var eg=s(93046),ey=s(67592),eb=s(11787),ew=s(68341),eN=s(2416),ek=s(78954),eC=s(75168),eA=s(34961);let eS=r.forwardRef(({className:e,orientation:t="horizontal",decorative:s=!0,...r},i)=>(0,a.jsx)(eC.b,{ref:i,decorative:s,orientation:t,className:(0,eA.cn)("shrink-0 bg-border","horizontal"===t?"h-[1px] w-full":"h-full w-[1px]",e),...r}));eS.displayName=eC.b.displayName;var eE=s(41819),eI=s(39049),eR=s(39461),eT=s(21);let e$=[{key:"account",label:"帳戶與付款"},{key:"financial",label:"財務與系統提醒"},{key:"insurance",label:"保險"},{key:"marketing",label:"行銷"}],eP=[{key:"login",label:"登入提醒",desc:"新裝置或新位置登入",group:"account",channels:["inApp","email","line"],emailKey:"login"},{key:"payment",label:"付款結果",desc:"贊助或預約付款成功或失敗",group:"account",channels:["inApp","email","line"],emailKey:"payment"},{key:"subscription",label:"贊助狀態",desc:"每月贊助啟用或取消",group:"account",channels:["inApp","email","line"],emailKey:"subscription"},{key:"booking",label:"預約通知",desc:"預約付款成功、變更",group:"account",channels:["inApp","line"]},{key:"credit_card_payment_due",label:"信用卡繳款提醒",desc:"信用卡繳款日前提前提醒",group:"account",channels:["inApp","line"]},{key:"goal_progress",label:"目標進度更新",desc:"達 25% / 50% / 75%",group:"financial",channels:["inApp","line"]},{key:"goal_achieved",label:"目標達成",desc:"完成目標的慶祝通知",group:"financial",channels:["inApp","line"]},{key:"monthly_record",label:"每月紀錄",desc:"月初提醒記錄本月帳戶餘額",group:"financial",channels:["inApp","line"],syncKeys:["settlement_reminder","monthly_summary"]},{key:"policy_premium_due",label:"保單繳費提醒",desc:"保單繳費前提前提醒",group:"insurance",channels:["inApp","line"],hasSubSettings:!0},{key:"marketing",label:"行銷訊息",desc:"新功能、優惠資訊",group:"marketing",channels:["inApp","email"],emailKey:"marketingEmails"}],eD={inApp:{label:"App",icon:eg.A},email:{label:"Email",icon:ey.A},line:{label:"LINE",icon:function({className:e}){return(0,a.jsx)("svg",{className:e,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",children:(0,a.jsx)("path",{d:"M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02
8c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314"})})}}},eF=[30,21,14,7,3,1],e_=[14,7,3];function eV(e){return Array.from(new Set(e.filter(e=>Number.isFinite(e)&&e>=0))).sort((e,t)=>t-e)}function eB(e){return e.syncKeys??[e.key]}function eL(e){let t={};for(let s of eP)if(s.channels.includes(e))for(let e of eB(s))t[e]=!0;return t}let ez={login:!1,payment:!1,subscription:!1,marketingEmails:!1};function eO(){let{toast:e}=(0,p.dj)(),{user:t}=(0,f.A)(),{isAdmin:s}=(0,eR.q)(),[i,l]=(0,r.useState)(!0),[n,c]=(0,r.useState)(!1),[o,u]=(0,r.useState)("idle"),[m,x]=(0,r.useState)(!1),[j,v]=(0,r.useState)(null),[b,w]=(0,r.useState)({email:{...ez},inApp:eL("inApp"),line:eL("line"),premiumReminderDays:[...e_]}),N=(0,r.useRef)({}),C=(0,r.useRef)(null),A=(0,r.useRef)(null),S=(0,r.useRef)(null),E=(0,r.useRef)(null),I=(0,r.useRef)(!0);(0,r.useEffect)(()=>()=>{E.current&&clearTimeout(E.current)},[]),(0,r.useEffect)(()=>{if(I.current=!0,!t?.uid||!y.db)return l(!1),()=>{I.current=!1};let e=(0,g.doc)(y.db,"users",t.uid),s=(0,g.aQ)(e,e=>{if(!I.current)return;let t=e.data()??{};x("string"==typeof t.lineUserId&&t.lineUserId.length>0);let s=t.notificationSettings??{},a=s.inApp&&"object"==typeof s.inApp?s.inApp:{},r=s.line&&"object"==typeof s.line?s.line:{},i=eL("inApp"),n=eL("line");for(let e of Object.keys(i))"boolean"==typeof a[e]&&(i[e]=a[e]);for(let e of Object.keys(n))"boolean"==typeof r[e]&&(n[e]=r[e]);let c={login:"boolean"==typeof s.login?s.login:ez.login,payment:"boolean"==typeof s.payment?s.payment:ez.payment,subscription:"boolean"==typeof s.subscription?s.subscription:ez.subscription,marketingEmails:"boolean"==typeof s.marketingEmails?s.marketingEmails:ez.marketingEmails};w(e=>({...e,email:c,inApp:i,line:n})),l(!1)},e=>{(0,k.vV)("[NotificationsSettings] user onSnapshot failed",e),l(!1)});return(async()=>{try{let e=await eT.s.getPreferences(t.uid),s=Array.isArray(e?.premiumReminderDays)?e.premiumReminderDays:[...e_];I.current&&w(e=>({...e,premiumReminderDays:eV(s)}))}catch(e){(0,k.vV)("[NotificationsSettings] load premiumReminderDays failed",e)}})(),()=>{I.current=!1,s(),A.current&&clearTimeout(A.current),S.current&&clearTimeout(S.current)}},[t?.uid]);let R=(0,r.useCallback)(async()=>{if(!t?.uid||!y.db)return;let e={...N.current},s=C.current;if(N.current={},C.current=null,0===Object.keys(e).length&&!s)return void u("idle");try{let a=[];if(Object.keys(e).length>0&&a.push((0,g.mZ)((0,g.doc)(y.db,"users",t.uid),{...e,updatedAt:new Date})),s&&a.push(eT.s.updatePreference(t.uid,"premiumReminderDays",eV(s))),await Promise.all(a),!I.current)return;u("saved"),S.current&&clearTimeout(S.current),S.current=setTimeout(()=>{I.current&&u("idle")},2e3)}catch(t){if((0,k.vV)("[NotificationsSettings] save failed",t),!I.current)return;N.current={...e,...N.current},s&&!C.current&&(C.current=s),u("error")}},[t?.uid]),T=(0,r.useCallback)(()=>{A.current&&clearTimeout(A.current),u("saving"),A.current=setTimeout(()=>{R()},500)},[R]),$=(0,r.useCallback)((e,t)=>{v({text:`${eD[e].label} 通知已${t?"開啟":"關閉"}`,key:Date.now()}),E.current&&clearTimeout(E.current),E.current=setTimeout(()=>{I.current&&v(null)},2e3)},[]),P=(0,r.useCallback)((e,t,s)=>{if("email"===t){if(!e.emailKey)return;let t=e.emailKey;w(e=>({...e,email:{...e.email,[t]:s}})),N.current[`notificationSettings.${t}`]=s}else if("inApp"===t){let t=eB(e);w(e=>{let a={...e.inApp};return t.forEach(e=>{a[e]=s}),{...e,inApp:a}}),t.forEach(e=>{N.current[`notificationSettings.inApp.${e}`]=s})}else if("line"===t){let t=eB(e);w(e=>{let a={...e.line};return t.forEach(e=>{a[e]=s}),{...e,line:a}}),t.forEach(e=>{N.current[`notificationSettings.line.${e}`]=s})}$(t,s),T()},[T,$]),D=(0,r.useCallback)((e,t)=>{w(s=>{let a=eV(t?[...s.premiumReminderDays,e]:s.premiumReminderDays.filter(t=>t!==e));return C.current=a,{...s,premiumReminderDays:a}}),T()},[T]),F=(0,r.useCallback)(async(t="system")=>{if(!y.auth?.currentUser)return void e({title:"尚未登入",description:"請先登入再測試通知"});c(!0);try{let s=await y.auth.currentUser.getIdToken(),a=await fetch("/api/me/notifications/test",{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({category:t})}),r=await a.json().catch(()=>({}));if(!a.ok)throw Error(r.error||`HTTP ${a.status}`);if(r.lineSent)e({title:"測試通知已送出",description:"請查看右上角鈴鐺與 LINE 官方帳號訊息"});
8else if("no_line_binding"===r.lineSkippedReason)e({title:"App 內通知已送出",description:"尚未綁定 LINE,請先綁定後再測試 LINE 推播"});else{let t=r.lineSkippedReason;e({title:"App 內通知已送出",description:t?`LINE 未推送:${t}`:"請查看右上角鈴鐺"})}}catch(t){e({title:"測試失敗",description:t instanceof Error?t.message:"請稍後再試"})}finally{c(!1)}},[e]);return(0,a.jsxs)(a.Fragment,{children:[j&&(0,a.jsx)("div",{role:"status","aria-live":"polite",className:"fixed inset-x-0 bottom-[calc(env(safe-area-inset-bottom)+5.5rem)] z-[60] flex justify-center px-6 md:hidden",children:(0,a.jsx)("div",{className:"animate-in fade-in slide-in-from-bottom-2 rounded-full bg-foreground px-4 py-2.5 text-sm font-medium text-background shadow-lg",children:j.text})},j.key),(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{className:"flex flex-row items-start justify-between gap-4 space-y-0",children:[(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)(d.ZB,{children:"通知設定"}),(0,a.jsx)(d.BT,{children:"切換後自動儲存"})]}),(0,a.jsxs)("div",{className:"flex items-center gap-2 shrink-0",children:[(0,a.jsx)(eU,{status:o,onRetry:R}),s&&(0,a.jsxs)("div",{className:"flex flex-wrap items-center gap-1",children:[(0,a.jsxs)(h.$,{type:"button",variant:"ghost",size:"sm",onClick:()=>void F("system"),disabled:n||!t?.uid,children:[(0,a.jsx)(eg.A,{className:"h-4 w-4 mr-1"}),n?"測試中...":"測試(系統)"]}),(0,a.jsx)(h.$,{type:"button",variant:"ghost",size:"sm",onClick:()=>void F("login"),disabled:n||!t?.uid,children:"測試登入"}),(0,a.jsx)(h.$,{type:"button",variant:"ghost",size:"sm",onClick:()=>void F("goal_progress"),disabled:n||!t?.uid,children:"測試目標"})]})]})]}),(0,a.jsxs)(d.Wu,{className:"space-y-6",children:[t?.uid&&(0,a.jsx)(eI.I,{uid:t.uid,initiallyLinked:m,onLinkedChange:x}),(0,a.jsx)(eS,{}),(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"hidden md:grid grid-cols-[1fr_64px_64px_64px] gap-x-4 items-center text-xs font-medium uppercase tracking-wider text-muted-foreground border-b pb-2",children:[(0,a.jsx)("div",{children:"事件"}),(0,a.jsx)("div",{className:"text-center",children:"App"}),(0,a.jsx)("div",{className:"text-center",children:"Email"}),(0,a.jsx)("div",{className:"text-center",children:"LINE"})]}),e$.map(e=>{let s=eP.filter(t=>
8t.group===e.key);return 0===s.length?null:(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("h4",{className:"text-xs font-semibold tracking-wider text-muted-foreground mt-3 mb-1",children:e.label}),s.map(e=>(0,a.jsx)(eM,{event:e,state:b,lineLinked:m,disabled:i||!t?.uid,onChannelChange:P,onPremiumDayToggle:D},e.key))]},e.key)})]})]})]})]})}function eU({status:e,onRetry:t}){return"idle"===e?null:"saving"===e?(0,a.jsxs)("span",{className:"text-xs text-muted-foreground flex items-center gap-1",children:[(0,a.jsx)(eb.A,{className:"h-3 w-3 animate-spin"}),"儲存中..."]}):"saved"===e?(0,a.jsxs)("span",{className:"text-xs text-green-600 dark:text-green-400 flex items-center gap-1",children:[(0,a.jsx)(ew.A,{className:"h-3 w-3"}),"已儲存"]}):(0,a.jsxs)("span",{className:"text-xs text-destructive flex items-center gap-1.5",children:[(0,a.jsx)(eN.A,{className:"h-3 w-3"}),"儲存失敗",(0,a.jsx)(h.$,{type:"button",variant:"link",size:"sm",className:"h-auto p-0 text-xs",onClick:t,children:"重試"})]})}function eM({event:e,state:t,lineLinked:s,disabled:r,onChannelChange:i,onPremiumDayToggle:l}){let n=eB(e)[0],c=!1!==t.inApp[n],d=!1!==t.line[n],o=!!e.emailKey&&t.email[e.emailKey],m=e.channels.includes("inApp"),h=e.channels.includes("email"),x=e.channels.includes("line"),p=[{channel:"inApp",supported:m,checked:c,disabled:r},{channel:"email",supported:h,checked:o,disabled:r||!0,hint:"Email 通知功能暫時停用"},{channel:"line",supported:x,checked:d,disabled:r||!s,hint:s?void 0:"請先綁定 LINE 才會推送"}];return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("div",{className:"flex items-center justify-between gap-3 py-3 md:hidden",children:[(0,a.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,a.jsx)("p",{className:"text-sm font-medium",children:e.label}),e.desc&&(0,a.jsx)("p",{className:"mt-0.5 text-xs text-muted-foreground",children:e.desc})]}),(0,a.jsx)("div",{className:"flex shrink-0 items-center gap-2",children:p.filter(e=>e.supported).map(t=>(0,a.jsx)(eW,{channel:t.channel,checked:t.checked,disabled:t.disabled,hint:t.hint,eventLabel:e.label,onChange:s=>i(e,t.channel,s)},t.channel))})]}),(0,a.jsxs)("div",{className:"hidden md:grid grid-cols-[1fr_64px_64px_64px] gap-x-4 items-center py-2",children:[(0,a.jsxs)("div",{className:"space-y-0.5 min-w-0",children:[(0,a.jsx)(u.J,{className:"cursor-default",children:e.label}),e.desc&&(0,a.jsx)("p",{className:"text-xs text-muted-foreground truncate",children:e.desc})]}),(0,a.jsx)(eZ,{supported:m,checked:c,disabled:r,onChange:t=>i(e,"inApp",t),tooltipUnsupported:`${e.label}不支援 App 內通知`}),(0,a.jsx)(eZ,{supported:h,checked:o,disabled:r||!0,onChange:t=>i(e,"email",t),tooltipUnsupported:`${e.label}不支援 Email 通知`,tooltipDisabled:"Email 通知功能暫時停用"}),(0,a.jsx)(eZ,{supported:x,checked:d,disabled:r||!s,onChange:t=>i(e,"line",t),tooltipUnsupported:`${e.label}不支援 LINE 通知`,tooltipDisabled:s?void 0:"請先綁定 LINE 才會推送"})]}),e.hasSubSettings&&"policy_premium_due"===e.key&&(0,a.jsx)("div",{className:"pl-4 pb-3 pt-1 border-l-2 border-muted ml-1 -mt-1",children:(0,a.jsx)(eH,{selectedDays:t.premiumReminderDays,disabled:r||!c&&!d,onToggle:l})})]})}function eW({channel:e,checked:t,disabled:s,hint:r,eventLabel:i,onChange:l}){let n=eD[e],c=n.icon,d=t?"已開啟":"已關閉";return(0,a.jsx)("button",{type:"button",role:"switch","aria-checked":t,"aria-label":`${i}:${n.label} 通知${d}`,title:r??`${n.label} 通知${d}`,disabled:s,onClick:()=>l(!t),className:(0,eA.cn)("flex h-11 w-11 items-center justify-center rounded-xl border transition-all active:scale-95",t?"border-accent/40 bg-accent/15 text-accent":"border-transparent bg-muted text-muted-foreground",s&&"cursor-not-allowed opacity-40 active:scale-100"),children:(0,a.jsx)(c,{className:"h-5 w-5"})})}function eZ({supported:e,checked:t,disabled:s,onChange:r,tooltipUnsupported:i,tooltipDisabled:l}){if(!e)return(0,a.jsx)(eE.m_,{content:i,children:(0,a.jsx)("div",{className:"flex justify-center cursor-help text-muted-foreground select-none",children:"—"})});let n=(0,a.jsx)(ek.d,{checked:t,disabled:s,onCheckedChange:r});return l?(0,a.jsx)("div",{className:"flex justify-center",children:(0,a.jsx)(eE.m_,{content:l,children:(0,a.jsx)("div",{children:n})})}):(0,a.jsx)("div",{className:"flex justify-center",children:n})}function eH({selectedDays:e,disabled:t,onToggle:s}){return(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"提前提醒天數(可多選)"}),(0,a.jsx)("div",{className:"flex flex-wrap gap-x-4 gap-y-2",children:eF.map(r=>{let i=`premium-reminder-day-${r}`;return(0,a.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,a.jsx)(S.S,{id:i,checked:e.includes(r),disabled:t,onCheckedChange:e=>s(r,!!e)}),(0,a.jsxs)(u.J,{htmlFor:i,className:"text-xs font-normal cursor-pointer",children:["提前 ",r," 天"]})]},r)})})]})}var eJ=s(79705),eG=s(575),eY=s(42603),eq=s(86754),eX=s(44844),eK=s(80345);function eQ(){let{toast:e}=(0,p.dj)(),{preferences:t,isLoading:s,toggleEnabled:i,setVolume:l,toggleCategory:n}=(0,eG.D)(),{playTestSound:c}=(0,eY.f)(),[o,m]=(0,r.useState)(!1),x=async()=>{m(!0);try{await c()?e({title:"測試音效播放成功",description:"您的瀏覽器已允許播放音效"}):e({title:"測試音效播放失敗",description:"請確保音效檔案存在且瀏覽器允許播放音效",variant:"destructive"})}catch(t){e({title:"測試音效播放失敗",description:"發生錯誤,請稍後再試",variant:"destructive"})}finally{m(!1)}},f=async e=>{await l(e[0])},j=Math.round(100*t.volume);return(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[t.enabled?(0,a.jsx)(eq.A,{className:"h-5 w-5"}):(0,a.jsx)(eX.A,{className:"h-5 w-5"}),"音效設定"]}),(0,a.jsx)(d.BT,{children:"管理應用程式的音效提醒功能"})]}),(0,a.jsxs)(d.Wu,{className:"space-y-6",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsxs)("div",{className:"space-y-0.5",children:[(0,a.jsx)(u.J,{htmlFor:"sound-enabled",className:"text-base font-medium",children:"啟用音效"}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"開啟後將在特定操作時播放音效提醒"})]}),(0,a.jsx)(ek.d,{id:"sound-enabled",checked:t.enabled,onCheckedChange:()=>i(),disabled:s})]}),(0,a.jsxs)("div",{className:"space-y-3",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)(u.J,{className:"text-base font-medium",children:"音量"}),(0,a.jsxs)("span",{className:"text-sm text-muted-foreground",children:[j,"%"]})]}),(0,a.jsxs)("div",{className:"flex items-center gap-4",children:[(0,a.jsx)(eX.A,{className:"h-4 w-4 text-muted-foreground"}),(0,a.jsx)(eJ.A,{value:[t.volume],onValueChange:f,min:0,max:1,step:.1,disabled:!t.enabled||s,className:"flex-1"}),(0,a.jsx)(eq.A,{className:"h-4 w-4 text-muted-foreground"})]})]}),(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsx)(u.J,{className:"text-base font-medium",children:"音效分類"}),(0,a.jsxs)("div",{className:"flex items-center justify-between rounded-lg border p-4",children:[(0,a.jsxs)("div",{className:"flex items-center gap-3",children:[(0,a.jsx)(eg.A,{className:"h-5 w-5 text-muted-foreground"}),(0,a.jsxs)("div",{className:"space-y-0.5",children:[(0,a.jsx)(u.J,{htmlFor:"alerts-enabled",children:"提醒音效"}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"通知、錯誤、警告、財務提醒等音效"})]})]}),(0,a.jsx)(ek.d,{id:"alerts-enabled",checked:t.categories.alerts,onCheckedChange:()=>n("alerts"),disabled:!t.enabled||s})]}),(0,a.jsxs)("div",{className:"flex items-center justify-between rounded-lg border p-4",children:[(0,a.jsxs)("div",{className:"flex items-center gap-3",children:[(0,a.jsx)(eK.A,{className:"h-5 w-5 text-muted-foreground"}),(0,a.jsxs)("div",{className:"space-y-0.5",children:[(0,a.jsx)(u.J,{htmlFor:"tasks-enabled",children:"任務音效"}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"任務完成、回測完成等音效"})]})]}),(0,a.jsx)(ek.d,{id:"tasks-enabled",checked:t.categories.tasks,onCheckedChange:()=>n("tasks"),disabled:!t.enabled||s})]})]}),(0,a.jsxs)("div",{className:"flex items-center justify-between rounded-lg border border-dashed p-4",children:[(0,a.jsxs)("div",{className:"space-y-0.5",children:[(0,a.jsx)(u.J,{className:"text-base font-medium",children:"測試音效"}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"點擊按鈕測試音效是否正常播放,同時解鎖瀏覽器自動播放限制"})]}),(0,a.jsx)(h.$,{variant:"outline",onClick:x,disabled:o,children:o?"播放中...":"播放測試音效"})]}),(0,a.jsx)("div",{className:"rounded-lg bg-muted/50 p-4",children:(0,a.jsxs)("div",{className:"flex items-start gap-2",children:[(0,a.jsx)(eN.A,{className:"h-5 w-5 text-amber-500 mt-0.5"}),(0,a.jsxs)("div",{className:"text-sm text-muted-foreground",children:[(0,a.jsx)("p",{className:"font-medium text-foreground mb-1",children:"注意事項"}),(0,a.jsxs)("ul",{className:"list-disc list-inside space-y-1",children:[(0,a.jsx)("li",{children:"部分瀏覽器需要先與頁面互動(如點擊按鈕)才能播放音效"}),(0,a.jsx)("li",{children:"請確保您的裝置未靜音且音量已調整至適當大小"}),(0,a.jsx)("li",{children:"音效設定會自動儲存並同步到雲端"})]})]})]})})]})]})}var e0=s(10250),e1=s(7004),e2=s(19726),e3=s(15268),e4=s(38187),e5=s(21016),e6=s(82331),e8=s(84569),e7=s(71899),e9=s(1933),te=s(54296),tt=s(42119),ts=s(3379);s(83881);let ta=async()=>
8{if(!y.auth||!y.auth.currentUser)throw Error("使用者未登入");try{let e=new w.FacebookAuthProvider;e.addScope("email"),e.addScope("public_profile");let t=await (0,w.linkWithPopup)(y.auth.currentUser,e);return(0,k.fH)("Facebook 帳戶連結成功:",y.auth.currentUser.uid),t}catch(e){if((0,k.vV)("連結 Facebook 帳戶失敗:",e),"auth/provider-already-linked"===e.code)throw Error("此 Facebook 帳戶已連結到其他帳號");if("auth/credential-already-in-use"===e.code)throw Error("此 Facebook 帳戶已被其他帳號使用");if("auth/popup-closed-by-user"===e.code)throw Error("登入視窗被關閉");if("auth/popup-blocked"===e.code)throw Error("彈出視窗被瀏覽器阻擋");throw Error(`連結 Facebook 帳戶失敗: ${e.message||"未知錯誤"}`)}};var tr=s(71931);function ti(){let{toast:e}=(0,p.dj)(),{user:t,auth:i}=(0,f.A)(),[l,n]=(0,r.useState)(!1),[c,m]=(0,r.useState)(!1),[x,j]=(0,r.useState)(null),[v,g]=(0,r.useState)(!1),[b,N]=(0,r.useState)(""),[C,A]=(0,r.useState)(""),[S,E]=(0,r.useState)(""),[I,R]=(0,r.useState)(!1),T=(()=>{if(!t)return[];let e=[{id:"password",name:"電子郵件/密碼",icon:(0,a.jsx)(ey.A,{className:"h-4 w-4"}),color:"bg-blue-500",isLinked:t.providerData.some(e=>"password"===e.providerId),canLink:!t.providerData.some(e=>"password"===e.providerId)},{id:"google.com",name:"Google",icon:(0,a.jsx)(e6.A,{className:"h-4 w-4"}),color:"bg-red-500",isLinked:t.providerData.some(e=>"google.com"===e.providerId),canLink:!0},{id:"line",name:"LINE",icon:(0,a.jsx)(e8.A,{className:"h-4 w-4"}),color:"bg-green-500",isLinked:c||t.providerData.some(e=>e.providerId===y.OIDC_LINE_PROVIDER_ID||e.providerId?.startsWith("oidc")),canLink:!0},{id:"facebook.com",name:"Facebook",icon:(0,a.jsx)(e7.A,{className:"h-4 w-4"}),color:"bg-blue-600",isLinked:t.providerData.some(e=>"facebook.com"===e.providerId),canLink:!0}],s=t.providerData.some(e=>"apple.com"===e.providerId);return((0,O.WV)()||s)&&e.push({id:"apple.com",name:"Apple",icon:(0,a.jsx)(e9.A,{className:"h-4 w-4"}),color:"bg-black",isLinked:s,canLink:(0,O.WV)()}),e})();(0,r.useEffect)(()=>{(async()=>{try{if(!i)return;let t=await (0,w.getRedirectResult)(i);if(!t)return;t.user?.providerData?.some(e=>e.providerId===y.OIDC_LINE_PROVIDER_ID||e.providerId?.startsWith("oidc"))&&(m(!0),e({title:"連結成功",description:"LINE 帳戶已與您目前的帳戶連結"}),window.location.reload())}catch(t){(0,k.vV)("處理 LINE 連結回傳失敗:",t),e({title:"連結失敗",description:t?.message||"請稍後再試",variant:"destructive"}),n(!1),j(null)}})()},[i,e]);let $=async()=>{if(!t||!i)return void e({title:"錯誤",description:"使用者未登入",variant:"destructive"});n(!0),j("google.com");try{let a=await (0,ts.gU)(),r=await a.user.getIdToken(),i=(await Promise.resolve().then(s.bind(s,76458))).functions;if(!i)throw Error("Firebase Functions 未初始化");let l=(0,tr.httpsCallable)(i,"linkGoogleAccount");await l({auth:{uid:t.uid},data:{googleToken:r}}),e({title:"連結成功",description:"Google 帳戶已成功連結到您的帳戶"}),window.location.reload()}catch(t){(0,k.vV)("連結 Google 帳戶失敗:",t),"auth/provider-already-linked"===t.code?e({title:"已連結",description:"此 Google 帳戶已連結到其他帳戶",variant:"destructive"}):"auth/credential-already-in-use"===t.code?e({title:"帳戶衝突",description:"此 Google 帳戶已被其他用戶使用",variant:"destructive"}):e({title:"連結失敗",description:t.message||"無法連結 Google 帳戶",variant:"destructive"})}finally{n(!1),j(null)}},P=async()=>{if(!t||!i)return void e({title:"錯誤",description:"使用者未登入",variant:"destructive"});n(!0),j("facebook.com");try{await ta(),e({title:"連結成功",description:"Facebook 帳戶已成功連結"}),window.location.reload()}catch(t){if((0,k.vV)("連結 Facebook 帳戶失敗:",t),t?.code==="auth/provider-already-linked"){e({title:"已連結",description:"此帳戶已連結 Facebook"}),n(!1),j(null);return}if(t?.code==="auth/credential-already-in-use"){e({title:"連結失敗",description:"此 Facebook 帳戶已被其他帳號使用",variant:"destructive"}),n(!1),j(null);return}e({title:"連結失敗",description:t?.message||"無法連結 Facebook 帳戶",variant:"destructive"})}finally{n(!1),j(null)}},D=async()=>
8{if(!t||!i)return void e({title:"錯誤",description:"使用者未登入",variant:"destructive"});n(!0),j("apple.com");try{await (0,O.uz)(),e({title:"連結成功",description:"Apple 帳戶已成功連結"}),window.location.reload()}catch(t){t?.code==="auth/provider-already-linked"?e({title:"已連結",description:"此帳戶已連結 Apple"}):t?.code==="auth/credential-already-in-use"?e({title:"連結失敗",description:"æ­¤ Apple 帳戶已被其他帳號使用",variant:"destructive"}):t?.code!=="auth/popup-closed-by-user"&&e({title:"連結失敗",description:t?.message||"無法連結 Apple 帳戶",variant:"destructive"})}finally{n(!1),j(null)}},F=async()=>{if(!t||!i)return void e({title:"錯誤",description:"使用者未登入",variant:"destructive"});n(!0),j("line");try{localStorage.setItem("lineLoginReturnUrl","/dashboard/settings");let e=new w.OAuthProvider(y.OIDC_LINE_PROVIDER_ID);e.addScope("openid"),e.addScope("profile"),e.addScope("email"),await (0,w.linkWithRedirect)(t,e)}catch(t){if((0,k.vV)("連結 LINE 帳戶失敗:",t),t?.code==="auth/provider-already-linked"){m(!0),e({title:"已連結",description:"此帳戶已連結 LINE"}),n(!1),j(null);return}e({title:"連結失敗",description:t?.message||"無法連結 LINE 帳戶",variant:"destructive"}),n(!1),j(null)}},_=async()=>{t&&i?(t.providerData.some(e=>"password"===e.providerId),g(!0)):e({title:"錯誤",description:"使用者未登入",variant:"destructive"})},V=async s=>{if(s.preventDefault(),!t||!i)return void e({title:"錯誤",description:"使用者未登入",variant:"destructive"});let a=t.providerData.some(e=>"password"===e.providerId);if(!C||!S)return void e({title:"請填寫所有欄位",description:"請輸入新密碼",variant:"destructive"});if(C!==S)return void e({title:"密碼不一致",description:"新密碼與確認密碼不符",variant:"destructive"});if(C.length<8)return void e({title:"密碼太短",description:"新密碼至少需要 8 個字元",variant:"destructive"});if(!/[A-Z]/.test(C)||!/[a-z]/.test(C)||!/[0-9]/.test(C)||!/[^A-Za-z0-9]/.test(C))return void e({title:"密碼格式錯誤",description:"密碼需包含大寫字母、小寫字母、數字和特殊字元",variant:"destructive"});R(!0);try{if(a&&b){let e=w.EmailAuthProvider.credential(t.email,b);await (0,w.reauthenticateWithCredential)(t,e)}else if(!a&&t.providerData.some(e=>"google.com"===e.providerId))try{let s=new w.GoogleAuthProvider;await (0,w.reauthenticateWithPopup)(t,s),e({title:"身份驗證成功",description:"Google 身份已重新驗證,可以設定密碼"})}catch(t){(0,k.vV)("Google 重新驗證失敗:",t),e({title:"驗證失敗",description:"無法驗證 Google 身份,請稍後再試",variant:"destructive"}),R(!1);return}await (0,w.updatePassword)(t,C),e({title:a?"密碼變更成功":"密碼設定成功",description:a?"您的密碼已成功更新":"您的密碼已成功設定"}),g(!1),N(""),A(""),E(""),window.location.reload()}catch(t){(0,k.vV)("密碼變更錯誤:",t),"auth/wrong-password"===t.code?e({title:"當前密碼錯誤",description:"請確認您輸入的當前密碼是否正確",variant:"destructive"}):"auth/weak-password"===t.code?e({title:"密碼強度不足",description:"新密碼強度不足,請使用更強的密碼",variant:"destructive"}):"auth/requires-recent-login"===t.code?e({title:"需要重新驗證",description:"為了安全起見,請重新登入後再嘗試設定密碼",variant:"destructive"}):e({title:"密碼變更失敗",description:t.message||"請稍後再試",variant:"destructive"})}finally{R(!1)}},B=async a=>{if(!t||!i)return void e({title:"錯誤",description:"使用者未登入",variant:"destructive"});if(t.providerData.filter(e=>"password"!==e.providerId).length<=1)return void e({title:"無法解除連結",description:"您必須至少保留一個登入方式",variant:"destructive"});n(!0);try{let r="line"===a?y.OIDC_LINE_PROVIDER_ID:a;await (0,w.unlink)(t,r);try{let e=(await Promise.resolve().then(s.bind(s,76458))).functions;if(e){let t=(0,tr.httpsCallable)(e,"unlinkAccount");await t({provider:r})}}catch{}e({title:"解除連結成功",description:"登入方式已成功解除連結"}),window.location.reload()}catch(t){if((0,k.vV)("解除連結失敗:",t),t?.code==="auth/no-such-provider")return void e({title:"未連結",description:"此登å
8…¥æ–¹å¼ç›®å‰æœªé€£çµ",variant:"destructive"});"functions/failed-precondition"===t.code?e({title:"無法解除連結",description:"您必須至少保留一個登入方式",variant:"destructive"}):e({title:"解除連結失敗",description:t.message||"無法解除連結",variant:"destructive"})}finally{n(!1)}};return t?(0,a.jsxs)("div",{className:"space-y-6",children:[(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(e2.A,{className:"h-5 w-5"}),"登入方式管理"]}),(0,a.jsx)(d.BT,{children:"管理您的帳戶登入方式,可以連結多個登入方式以提高便利性"})]}),(0,a.jsx)(d.Wu,{className:"space-y-4",children:T.map(e=>(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between p-4 border rounded-lg",children:[(0,a.jsxs)("div",{className:"flex items-center gap-3",children:[(0,a.jsx)("div",{className:`p-2 rounded-full ${e.color} text-white`,children:e.icon}),(0,a.jsxs)("div",{children:[(0,a.jsx)("p",{className:"font-medium",children:e.name}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:e.isLinked?"已連結":"未連結"})]})]}),(0,a.jsx)("div",{className:"flex items-center gap-2",children:e.isLinked?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(e4.E,{variant:"secondary",className:"flex items-center gap-1",children:[(0,a.jsx)(eK.A,{className:"h-3 w-3"}),"已連結"]}),e.canLink&&"password"!==e.id&&(0,a.jsxs)(h.$,{variant:"outline",size:"sm",onClick:()=>B(e.id),disabled:l,children:[(0,a.jsx)(te.A,{className:"h-4 w-4 mr-1"}),"解除連結"]}),"password"===e.id&&(0,a.jsxs)(h.$,{variant:"outline",size:"sm",onClick:_,disabled:l,children:[(0,a.jsx)(tt.A,{className:"h-4 w-4 mr-1"}),"變更密碼"]})]}):e.canLink&&(0,a.jsx)(h.$,{variant:"outline",size:"sm",onClick:"google.com"===e.id?$:"line"===e.id?F:"facebook.com"===e.id?P:"apple.com"===e.id?D:"password"===e.id?_:()=>{},disabled:l||x===e.id,children:x===e.id?"處理中...":(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(tt.A,{className:"h-4 w-4 mr-1"}),"password"===e.id?"設定密碼":"連結"]})})})]}),"password"===e.id&&v&&(0,a.jsx)("div",{className:"ml-4 p-4 border rounded-lg bg-muted/50",children:(0,a.jsxs)("form",{onSubmit:V,className:"space-y-4",children:[(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{className:"text-sm font-medium",children:t?.providerData.some(e=>"password"===e.providerId)?"密碼管理":"設定密碼"}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:t?.providerData.some(e=>"password"===e.providerId)?"變更您的登入密碼":"為您的帳戶設定密碼,以便使用 電子郵件/密碼登入"})]}),t?.providerData.some(e=>"password"===e.providerId)&&(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"current-password",children:"當前密碼"}),(0,a.jsx)(o.p,{id:"current-password",type:"password",autoComplete:"current-password",value:b,onChange:e=>N(e.target.value),placeholder:"請輸入當前密碼",required:!0})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"new-password",children:t?.providerData.some(e=>"password"===e.providerId)?"新密碼":"密碼"}),(0,a.jsx)(o.p,{id:"new-password",type:"password",autoComplete:"new-password",value:C,onChange:e=>A(e.target.value),placeholder:"請輸入密碼(至少 8 個字元)",required:!0}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"密碼需包含:大寫字母、小寫字母、數字、特殊字元"})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"confirm-password",children:"確認密碼"}),(0,a.jsx)(o.p,{id:"confirm-password",type:"password",autoComplete:"new-password",value:S,onChange:e=>E(e.target.value),placeholder:"請再次輸入密碼",required:!0})]}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)(h.$,{type:"submit",disabled:I,children:I?"處理中...":t?.providerData.some(e=>"password"===e.providerId)?"確認變更":"確認設定"}),(0,a.jsx)(h.$,{type:"button",variant:"outline",onClick:()=>{g(!1),N(""),A(""),E("")},children:"取消"})]})]})})]},e.id))})]}),(0,a.jsxs)(e5.Fc,{children:[(0,a.jsx)(eN.A,{className:"h-4 w-4"}),(0,a.jsxs)(e5.TN,{children:[(0,a.jsx)("strong",{children:"注意:"}),(0,a.jsxs)("ul",{className:"mt-2 space-y-1 text-sm",children:[(0,a.jsx)("li",{children:"• 您必須至少保留一個登入方式"}),(0,a.jsx)("li",{children:"• 連結多個登入方式可以讓您使用任一方式登入"}),(0,a.jsx)("li",{children:"• 解除連結後,您將無法使用該方式登入"})]})]})]})]}):(0,a.jsxs)(e5.Fc,{children:[(0,a.jsx)(eN.A,{className:"h-4 w-4"}),(0,a.jsx)(e5.TN,{children:"請先登入以管理您的帳戶連結設定"})]})}var tl=s(37014);function tn({hasPassword:e,totpEnrolled:t}){let{toast:s}=(0,p.dj)(),{user:i,auth:l}=(0,f.A)(),d=l||y.auth,[m,j]=(0,r.useState)(!1),[v,b]=(0,r.useState)(!0),[N,C]=(0,r.useState)("idle"),[A,S]=(0,r.useState)(null),[E,I]=(0,r.useState)(!1),R=(0,n.mN)({resolver:(0,c.u)(X.yE),defaultValues:{password:""}}),T=(0,r.useCallback)(async()=>
8{if(!i||!y.db)return void b(!1);try{let e=await (0,g.getDoc)((0,g.doc)(y.db,"users",i.uid));j(e.data()?.emailLinkSignInEnabled===!0)}catch(e){(0,k.vV)("讀取 emailLinkSignInEnabled 失敗:",e)}finally{b(!1)}},[i]);(0,r.useEffect)(()=>{T()},[T]),(0,r.useEffect)(()=>{!t&&m&&j(!1)},[t,m]);let $=!!(i?.emailVerified&&t),P=async t=>{if(i&&d){I(!0);try{if(e){if(!t.password.trim())return void s({title:"請輸入目前密碼",variant:"destructive"});let e=w.EmailAuthProvider.credential(i.email,t.password);await (0,w.reauthenticateWithCredential)(i,e)}else{let e=i.providerData[0]?.providerId;if("google.com"===e)await (0,w.reauthenticateWithPopup)(i,new w.GoogleAuthProvider);else if("facebook.com"===e)await (0,w.reauthenticateWithPopup)(i,new w.FacebookAuthProvider);else{if(!(e===y.OIDC_LINE_PROVIDER_ID||e?.startsWith("oidc")))return void s({title:"不支援的登入方式",description:"請先綁定電子郵件/密碼後再變更此設定。",variant:"destructive"});await (0,w.reauthenticateWithPopup)(i,new w.OAuthProvider(y.OIDC_LINE_PROVIDER_ID))}}if(null===A)return;await (0,tl.callFn)("setEmailLinkSignInEnabled",{enabled:A}),j(A),C("idle"),S(null),R.reset(),s({title:A?"已啟用連結登入":"已關閉連結登入",description:A?"您現在可以使用「寄送登入連結」登入,每次仍須輸入驗證器 6 碼。":"電子郵件連結登入已關閉。"})}catch(t){(0,k.vV)("更新 emailLinkSignInEnabled 失敗:",t);let e=t?.code;if("auth/popup-closed-by-user"===e||"auth/cancelled-popup-request"===e){C("idle"),S(null);return}s({title:"設定失敗",description:t?.message||"請稍後再試",variant:"destructive"})}finally{I(!1)}}};return(0,a.jsxs)("div",{className:"space-y-3 rounded-lg border bg-muted/20 p-4",children:[(0,a.jsxs)("div",{className:"flex items-start justify-between gap-4",children:[(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)(ey.A,{className:"h-4 w-4"}),(0,a.jsx)(u.J,{htmlFor:"email-link-sign-in",children:"電子郵件連結登入"})]}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"啟用後可在登入頁使用「寄送登入連結」。須完成信箱驗證、綁定驗證器 App,且每次登入仍須輸入 TOTP 6 碼。"}),i?.emailVerified?null:(0,a.jsx)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:"請先完成信箱驗證。"}),i?.emailVerified&&!t?(0,a.jsx)("p",{className:"text-xs text-amber-600 dark:text-amber-400",children:"請先綁定驗證器 App。"}):null]}),(0,a.jsx)(ek.d,{id:"email-link-sign-in",checked:m,disabled:v||E||"reauth"===N||!m&&!$,onCheckedChange:e=>{if(i){if(e){if(!i.emailVerified)return void s({title:"尚未完成信箱驗證",description:"請先驗證電子郵件後再啟用連結登入。",variant:"destructive"});if(!t)return void s({title:"請先綁定驗證器",description:"啟用連結登入前須綁定 TOTP 驗證器 App。",variant:"destructive"})}S(e),C("reauth"),R.reset()}},"aria-label":"啟用電子郵件連結登入"})]}),"reauth"===N?(0,a.jsx)(x.lV,{...R,children:(0,a.jsxs)("form",{onSubmit:R.handleSubmit(P),className:"space-y-3 border-t pt-3",children:[(0,a.jsx)("p",{className:"text-sm font-medium",children:A?"啟用前請先驗證身份":"關閉前請先驗證身份"}),e?(0,a.jsx)(x.zB,{control:R.control,name:"password",render:({field:e})=>(0,a.jsxs)(x.eI,{children:[(0,a.jsx)(x.lR,{children:"目前密碼"}),(0,a.jsx)(x.MJ,{children:(0,a.jsx)(o.p,{type:"password",autoComplete:"current-password",...e})}),(0,a.jsx)(x.C5,{})]})}):(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"將開啟彈出視窗請您重新登入以驗證身份。"}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)(h.$,{type:"submit",disabled:E,children:E?"處理中…":"確認"}),(0,a.jsx)(h.$,{type:"button",variant:"outline",onClick:()=>{C("idle"),S(null),R.reset()},children:"取消"})]})]})}):null]})}async function tc(){try{await (0,tl.callFn)("setEmailLinkSignInEnabled",{enabled:!1})}catch(e){(0,k.vV)("解除 TOTP 後關閉 emailLinkSignInEnabled 失敗
8:",e)}}var td=s(65396),to=s(95897);function tu(){let{toast:e}=(0,p.dj)(),{user:t,auth:s}=(0,f.A)(),i=s||y.auth,l=(0,to.$)(t),[m,j]=(0,r.useState)("idle"),[v,b]=(0,r.useState)(!1),N=(0,n.mN)({resolver:(0,c.u)(X.yE),defaultValues:{password:""}}),C=l.hasPassword,{emailVerified:A,isEmailProvider:S,isSending:E,resend:I}=function(){let{user:e,auth:t}=(0,f.A)(),[s,a]=(0,r.useState)(null),[i,l]=(0,r.useState)(!1),n=e?.providerData?.some(e=>"password"===e.providerId)??!1;(0,r.useEffect)(()=>{let s=!1,r=async()=>{if(!e?.uid||!t?.currentUser){s||a(null);return}try{if(t.currentUser.emailVerified){s||a(!0);return}if(y.db){let t=await (0,g.getDoc)((0,g.doc)(y.db,y.USERS,e.uid));if(t.exists()&&t.data()?.emailVerified===!0){s||a(!0);return}}s||a(!1)}catch(e){(0,k.vV)("檢查 Email 驗證狀態失敗:",e),s||a(t.currentUser?.emailVerified??!1)}};r();let i=t?.onAuthStateChanged(e=>{e?.emailVerified?a(!0):e&&r()});return()=>{s=!0,i?.()}},[e?.uid,t]);let c=(0,r.useCallback)(async()=>{if(t?.currentUser&&!i){l(!0);try{await (0,w.sendEmailVerification)(t.currentUser,{url:`${window.location.origin}/auth?verified=true`,handleCodeInApp:!1}),y.db&&e?.uid&&await (0,g.mZ)((0,g.doc)(y.db,y.USERS,e.uid),{lastEmailVerificationReminder:(0,g.serverTimestamp)()}),(0,k.fH)("Email 驗證信已重新發送")}catch(e){throw(0,k.vV)("發送驗證信失敗:",e),e}finally{l(!1)}}},[t,i,e?.uid]);return{emailVerified:s,isEmailProvider:n,needsVerification:n&&!1===s,isSending:i,resend:c}}(),R=async()=>{try{await I(),e({title:"驗證信已寄出",description:"請檢查您的信箱(包括垃圾郵件)"})}catch(t){e({title:"寄送失敗",description:"auth/too-many-requests"===("object"==typeof t&&null!==t&&"code"in t?String(t.code):"")?"請求過於頻繁,請稍後再試":t instanceof Error?t.message:"請稍後再試",variant:"destructive"})}},T=async s=>{if(t&&i&&0!==l.enrolledFactors.length){b(!0);try{if(C){if(!s.password.trim()){e({title:"請輸入目前密碼",variant:"destructive"}),b(!1);return}let a=w.EmailAuthProvider.credential(t.email,s.password);await (0,w.reauthenticateWithCredential)(t,a)}else{let s=t.providerData[0]?.providerId;if("google.com"===s)await (0,w.reauthenticateWithPopup)(t,new w.GoogleAuthProvider);else if("facebook.com"===s)await (0,w.reauthenticateWithPopup)(t,new w.FacebookAuthProvider);else if(s===y.OIDC_LINE_PROVIDER_ID||s?.startsWith("oidc"))await (0,w.reauthenticateWithPopup)(t,new w.OAuthProvider(y.OIDC_LINE_PROVIDER_ID));else{e({title:"不支援的登入方式",variant:"destructive"}),b(!1);return}}let a=l.enrolledFactors[0];await (0,w.multiFactor)(t).unenroll(a),l.refreshEnrolled(),j("idle"),N.reset(),e({title:"已解除綁定",description:"驗證器 App 已解除,登入時不再要求輸入 6 碼。"}),(0,k.fH)("TOTP 已解除綁定"),await tc()}catch(s){(0,k.vV)("解除 TOTP 綁定失敗:",s);let t="object"==typeof s&&null!==s&&"code"in s?String(s.code):"";if("auth/user-token-expired"===t){e({title:"工作階段已過期",description:"請重新登入後再試一次。",variant:"destructive"}),j("idle");return}if("auth/popup-closed-by-user"===t||"auth/cancelled-popup-request"===t){e({title:"已取消"}),j("idle");return}if("auth/wrong-password"===t||"auth/invalid-credential"===t)return void e({title:"驗證失敗",description:"密碼不正確,請重試。",variant:"destructive"});e({title:"解除綁定失敗",description:s instanceof Error?s.message:"請稍後再試",variant:"destructive"})}finally{b(!1)}}};return(0,a.jsxs)("div",{className:"space-y-6",children:[S&&null!==A&&(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(ey.A,{className:"h-5 w-5"})," Email 驗證"]}),(0,a.jsx)(d.BT,{children:"驗證電子郵件以保護帳戶安全並接收重要通知"})]}),(0,a.jsx)(d.Wu,{children:A?(0,a.jsxs)("div",{className:"flex items-center gap-2 rounded-lg border border-green-200 bg-green-50 p-3 text-sm text-green-700 dark:border-green-800 dark:bg-green-900/20 dark:text-green-300",children:[(0,a.jsx)(e0.A,{className:"h-4 w-4 shrink-0"}),(0,a.jsxs)("span",{children:["你的 Email(",t?.email,")已完成驗證。"]})]}):(0,a.jsxs)("div",{className:"space-y-3 rounded-lg border border-yellow-200 bg-yellow-50 p-3 dark:border-yellow-800 dark:bg-yellow-900/20",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 text-sm text-yellow-800 dark:text-yellow-200",children:[(0,a.jsx)(e1.A,{className:"h-4 w-4 shrink-0"}
8),(0,a.jsx)("span",{children:"你的 Email 尚未驗證。完成驗證後才能啟用完整功能與帳戶保護。"})]}),(0,a.jsx)(h.$,{size:"sm",onClick:()=>void R(),disabled:E,children:E?"發送中...":"重新發送驗證信"})]})})]}),(0,a.jsx)(ti,{}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(e2.A,{className:"h-5 w-5"})," 安全性設定"]}),(0,a.jsx)(d.BT,{children:"管理您的帳戶安全性與雙因素認證"})]}),(0,a.jsxs)(d.Wu,{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)(e3.A,{className:"h-4 w-4"}),(0,a.jsx)(u.J,{children:"驗證器 App(TOTP)"})]}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"使用 Google Authenticator 等 App 產生 6 碼,登入時作為第二因素驗證。"}),l.enrolledFactors.length>0?"reauth"===m?(0,a.jsx)(x.lV,{...N,children:(0,a.jsxs)("form",{onSubmit:N.handleSubmit(e=>void T(e)),className:"space-y-3 rounded-lg border bg-muted/30 p-3",children:[(0,a.jsx)("p",{className:"text-sm font-medium",children:"解除綁定前請先驗證身份"}),C?(0,a.jsx)(x.zB,{control:N.control,name:"password",render:({field:e})=>(0,a.jsxs)(x.eI,{children:[(0,a.jsx)(x.lR,{children:"目前密碼"}),(0,a.jsx)(x.MJ,{children:(0,a.jsx)(o.p,{type:"password",placeholder:"請輸入目前密碼",autoComplete:"current-password",...e})}),(0,a.jsx)(x.C5,{})]})}):(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"將開啟彈出視窗請您重新登入。"}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)(h.$,{type:"submit",variant:"destructive",disabled:v,children:v?"處理中...":"確認解除綁定"}),(0,a.jsx)(h.$,{type:"button",variant:"outline",onClick:()=>{j("idle"),N.reset()},children:"取消"})]})]})}):(0,a.jsxs)("div",{className:"space-y-2 rounded-lg border bg-muted/30 p-3",children:[(0,a.jsx)("p",{className:"text-sm font-medium",children:"已綁定驗證器"}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:l.enrolledFactors.map(e=>e.displayName||"驗證器").join("、")}),(0,a.jsx)(h.$,{type:"button",variant:"outline",size:"sm",onClick:()=>{0!==l.enrolledFactors.length&&(j("reauth"),N.reset())},children:"解除綁定"})]}):(0,a.jsx)(td.e,{enrollment:l})]}),(0,a.jsx)(tn,{hasPassword:!!C,totpEnrolled:l.enrolledFactors.length>0})]})]})]})}var tm=s(48113),th=s(45762),tx=s(46955),tp=s(40975),tf=s(31283),tj=s(26052),tv=s.n(tj);let tg={pending:"待完成授權",authorized:"待付款",paid:"已付款",cancelled:"已取消"};function ty(){let{user:e}=(0,f.A)(),{toast:t}=(0,p.dj)(),[s,i]=(0,r.useState)([]),[l,n]=(0,r.useState)(!0),[c,o]=(0,r.useState)(null),[u,m]=(0,r.useState)(null),[x,j]=(0,r.useState)(null),{startPayment:v,isPaymentLoading:g}=(0,tx.L)();(0,r.useEffect)(()=>{if(!e?.uid){i([]),o(null),n(!1);return}let t=!1;return n(!0),o(null),th.y.getUserBookings(e.uid).then(e=>{t||(i(e),o(null))}).catch(s=>{if(!t){let t=s instanceof Error?s.message:String(s);K.Cp(s instanceof Error?s:Error(t),{level:"error",extra:{message:"載入預約列表失敗",userId:e.uid},tags:{source:"UserBookingsSettings.loadBookings"}}),i([]),o("無法載入預約列表,請重新整理頁面或稍後再試。")}}).finally(()=>{t||n(!1)}),()=>{t=!0}},[e?.uid]);let y=async e=>{if(("pending"===e.status||"authorized"===e.status)&&!x)try{let t=await th.y.getBookingById(e.id);t&&await v(t)}catch(e){(0,k.vV)("前往付款失敗",e)}},b=async()=>{if(!u)return;let e=u.id;j(e);try{await th.y.cancelBooking(e),t({title:"已取消預約",description:"時段已釋出。"}),i(t=>t.map(t=>t.id===e?{...t,status:"cancelled"}:t)),m(null)}catch(e){(0,k.vV)("取消預約失敗",e),t({variant:"destructive",title:"取消預約失敗",description:function(e){if("object"==typeof e&&null!==e&&"code"in e&&"string"==typeof e.code){let t=e.code;if("permission-denied"===t)return"您沒有權限取消此預約。";if("functions/not-found"===t||"not-found"===t)return"找不到預約資料。";if("failed-precondition"===t)return"此預約狀態已變更,無法取消。"}return"無法取消預約,請稍後再試。"}(e)})}finally{j(null)}};if(l)return(0,a.jsx)(d.Zp,{className:"p-8 flex items-center justify-center",children:(0,a.jsx)(eb.A,{className:"h-8 w-8 animate-spin text-muted-foreground"})});if(c)return(0,a.jsxs)(d.Zp,{className:"p-8 text-center",children:[(0,a.jsx)("p",{className:"text-destructive mb-2",children:c}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"若問題持續,請聯絡客服。"})]});if(0===s.length)return(0,a.jsx)(d.Zp,{className:"p-8 text-center text-muted-foreground",children:(0,a.jsx)("p",{children:"目前沒有預約記錄"})});let w=g||null!==x;return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(tm.Lt,{open:null!==u,onOpenChange:e=>{e||null!==x||m(null)},children:(0,a.jsxs)(tm.EO,{children:[(0,a.jsxs)(tm.wd,{children:[(0,a.jsx)(tm.r7,{children:"確認取消預約?"}),(0,a.jsx)(tm.$v,{children:"取消後將釋出該時段供他人預約。若尚未完成付款,您將不需再為此筆進行付款。"})]}),(0,a.jsxs)(tm.ck,{children:[(0,a.jsx)(tm.Zr,{disabled:null!==x,children:"返回"}),(0,a.jsx)(h.$,{type:"button",variant:"destructive",disabled:null!==x,onClick:()=>void b(),children:null!==x?(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin"}):"確認取消"})]})]})}),(0,a.jsxs)(d.Zp,{className:"p-4",children:[(0,a.jsx)("h3",{className:"text-sm font-semibold mb-3",children:"我的預約"}),(0,a.jsx)("ul",{className:"space-y-3",children:s.map(e=>(0,a.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 py-3 border-b last:border-0",children:[(0,a.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,a.jsx)("p",{className:"font-medium truncate",children:e.advisorName??"顧問"}),(0,a.jsxs)("p",{className:"text-sm text-muted-foreground",children:[e.date," ",e.time," \xb7"," ",tg[e.status]??e.status]})]}),(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[("pending"===e.status||"authorized"===e.status)&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(h.$,{type:"button",size:"sm",variant:"outline",disabled:w,onClick:()=>m(e),children:"取消預約"}),(0,a.jsx)(h.$,{size:"sm",onClick:()=>y(e),disabled:w,children:g?(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin"}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(tp.A,{className:"h-4 w-4 mr-1"}),"前往付款"]})})]}),(0,a.jsx)(h.$,{size:"sm",variant:"outline",asChild:!0,children:(0,a.jsxs)(tv(),{href:`/payment/success?bookingId=${e.id}`,children:[(0,a.jsx)(tf.A,{className:"h-4 w-4 mr-1"}),"查看"]})})]})]},e.id))})]})]})}var tb=s(4530);async function tw(e,t){let s=y.auth?.currentUser;if(!s)throw Error("請先登入");let a=await s.getIdToken();return fetch(e,{...t,headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`,...t?.headers??{}}})}function tN(){let{toast:e}=(0,p.dj)(),[t,s]=(0,r.useState)([]),[i,l]=(0,r.useState)(""),[n,c]=(0,r.useState)(!0),[m,x]=(0,r.useState)(!1),[f,j]=(0,r.useState)(null),v=(0,r.useCallback)(async()=>{try{c(!0);let e=await tw("/api/tools/v1/api-keys"),t=await e.json();if(!e.ok)throw Error(t?.error?.message??t?.error??"載入失敗");s(t.data?.keys??[])}catch(t){(0,k.vV)("載入 Tool API Keys 失敗",t),e({title:"載入失敗",variant:"destructive"})}finally{c(!1)}},[e]);(0,r.useEffect)(()=>{v()},[v]);let g=async()=>
8{if(i.trim()){x(!0);try{let t=await tw("/api/tools/v1/api-keys",{method:"POST",body:JSON.stringify({label:i.trim()})}),s=await t.json();if(!t.ok)throw Error(s?.error?.message??"建立失敗");j(s.data?.apiKey??null),l(""),await v(),e({title:"API Key 已建立",description:"請立即複製,僅顯示一次。"})}catch(t){(0,k.vV)("建立 API Key 失敗",t),e({title:"建立失敗",variant:"destructive"})}finally{x(!1)}}},y=async t=>{try{let s=await tw(`/api/tools/v1/api-keys/${t}`,{method:"DELETE"});if(!s.ok){let e=await s.json();throw Error(e?.error?.message??"撤銷失敗")}await v(),e({title:"已撤銷 API Key"})}catch(t){(0,k.vV)("撤銷 API Key 失敗",t),e({title:"撤銷失敗",variant:"destructive"})}},b=async()=>{f&&(await navigator.clipboard.writeText(f),e({title:"已複製到剪貼簿"}))};return(0,a.jsx)("div",{className:"space-y-6",children:(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(tb.A,{className:"h-5 w-5"}),"理財工具 API Key"]}),(0,a.jsx)(d.BT,{children:"供腳本或外部整合呼叫試算 API(房貸、複利、損益平衡、財務摘要)。請勿提交至版控。"})]}),(0,a.jsxs)(d.Wu,{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsxs)("div",{className:"flex-1 space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"tool-api-label",children:"名稱"}),(0,a.jsx)(o.p,{id:"tool-api-label",value:i,onChange:e=>l(e.target.value),placeholder:"例如:本機腳本"})]}),(0,a.jsx)(h.$,{className:"self-end",onClick:g,disabled:m||!i.trim(),children:m?(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin"}):"建立 Key"})]}),f&&(0,a.jsxs)("div",{className:"rounded-md border border-amber-500/40 bg-amber-500/10 p-3 text-sm",children:[(0,a.jsx)("p",{className:"font-medium mb-2",children:"新 Key(僅顯示一次)"}),(0,a.jsx)("code",{className:"block break-all text-xs mb-2",children:f}),(0,a.jsxs)(h.$,{size:"sm",variant:"outline",onClick:b,children:[(0,a.jsx)(ec.A,{className:"h-3 w-3 mr-1"}),"複製"]})]}),n?(0,a.jsx)(eb.A,{className:"h-5 w-5 animate-spin text-muted-foreground"}):0===t.length?(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"尚無 API Key"}):(0,a.jsx)("ul",{className:"space-y-2",children:t.map(e=>(0,a.jsxs)("li",{className:"flex items-center justify-between rounded-md border px-3 py-2 text-sm",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("span",{className:"font-medium",children:e.label}),(0,a.jsxs)("span",{className:"text-muted-foreground ml-2",children:["…",e.prefix]}),e.revokedAt&&(0,a.jsx)("span",{className:"ml-2 text-destructive",children:"(已撤銷)"})]}),!e.revokedAt&&(0,a.jsx)(h.$,{size:"sm",variant:"ghost",onClick:()=>y(e.id),children:(0,a.jsx)(te.A,{className:"h-4 w-4"})})]},e.id))})]})]})})}var tk=s(57670);let tC=I.Ik({id:I.Yj(),actorType:I.k5(["advisor","admin"]),advisorUid:I.Yj().nullable().optional(),advisorProfileId:I.Yj().nullable().optional(),userId:I.Yj(),collection:I.Yj(),docId:I.Yj(),operation:I.k5(["create","update","delete"]),before:I.g1(I.Yj(),I.L5()).nullable().optional(),after:I.g1(I.Yj(),I.L5()).nullable().optional(),editedAt:I.Yj().nullable().optional()}),tA=I.Ik({edits:I.YO(tC),hasMore:I.zM(),nextCursor:I.Yj().nullable()});var tS=s(22573);let tE={accounts:"帳戶",transactions:"交易",account_monthly_balances:"月餘額",monthly_unallocated:"月度未分配",income_distribution_rules:"收入分配規則",assets:"資產",liabilities:"負債",investments:"投資",goals:"目標",financial_indicators:"財務指標"},tI={create:"新增",update:"更新",delete:"刪除"},tR={create:"default",update:"secondary",delete:"destructive"};function tT({edit:e}){let t="admin"===e.actorType?"管理員":"顧問";return(0,a.jsxs)("div",{className:"flex flex-col sm:flex-row sm:items-center gap-2 py-3 border-b last:border-b-0",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 min-w-0 flex-1",children:[(0,a.jsx)(e4.E,{variant:tR[e.operation]||"outline",className:"shrink-0",children:tI[e.operation]||e.operation}),(0,a.jsx)("span",{className:"text-sm font-medium truncate",children:tE[e.collection]||e.collection}),(0,a.jsx)(e4.E,{variant:"outline",className:"text-xs shrink-0",children:t})]}),(0,a.jsx)("span",{className:"text-xs text-muted-foreground shrink-0",children:function(e){if(!e)return"—";
8try{return new Date(e).toLocaleString("zh-TW",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"})}catch{return e}}(e.editedAt)})]})}function t$(){let{edits:e,isLoading:t,error:s,hasMore:i,load:l,loadMore:n}=function(){let{user:e}=(0,f.A)(),[t,s]=(0,r.useState)([]),[a,i]=(0,r.useState)(!1),[l,n]=(0,r.useState)(null),[c,d]=(0,r.useState)(!1),[o,u]=(0,r.useState)(null),m=(0,r.useCallback)(async t=>{if(e){i(!0),n(null);try{let a=await e.getIdToken(),r=new URLSearchParams;r.set("limit","20"),t&&r.set("cursor",t);let i=await fetch(`/api/me/financial-edits?${r.toString()}`,{headers:{Authorization:`Bearer ${a}`}});if(!i.ok){let e=await i.json().catch(()=>({}));throw Error("string"==typeof e.error?e.error:`HTTP ${i.status}`)}let l=await i.json(),n=tA.safeParse(l);if(!n.success)throw Error("回應格式錯誤");t?s(e=>[...e,...n.data.edits]):s(n.data.edits),d(n.data.hasMore),u(n.data.nextCursor)}catch(e){n(e instanceof Error?e.message:"載入失敗")}finally{i(!1)}}},[e]),h=(0,r.useCallback)(()=>{c&&o&&m(o)},[c,o,m]);return{edits:t,isLoading:a,error:l,hasMore:c,load:m,loadMore:h}}();return(0,r.useEffect)(()=>
8{l()},[l]),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(tS.A,{className:"h-5 w-5"}),"財務資料修改紀錄"]})}),(0,a.jsxs)(d.Wu,{children:[(0,a.jsx)("p",{className:"text-sm text-muted-foreground mb-4",children:"以下是顧問或管理員代為修改您財務資料的紀錄。"}),t&&0===e.length&&(0,a.jsx)("div",{className:"flex items-center justify-center py-8",children:(0,a.jsx)(eb.A,{className:"h-6 w-6 animate-spin text-muted-foreground"})}),s&&(0,a.jsx)("p",{className:"text-sm text-destructive",children:s}),!t&&0===e.length&&!s&&(0,a.jsx)("p",{className:"text-sm text-muted-foreground text-center py-8",children:"暫無修改紀錄"}),(0,a.jsx)("div",{className:"divide-y",children:e.map(e=>(0,a.jsx)(tT,{edit:e},e.id))}),i&&(0,a.jsx)("div",{className:"flex justify-center mt-4",children:(0,a.jsxs)(h.$,{variant:"outline",size:"sm",onClick:n,disabled:t,children:[t?(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin mr-2"}):null,"載入更多"]})})]})]})}var tP=s(37146),tD=s(8643),tF=s(20290),t_=s(82721);async function tV(e){let t=await e.json().catch(()=>({}));if(!e.ok){let s=Error(t.error||`Request failed: ${e.status}`);throw s.code=t.code,s.current=t.current,s.max=t.max,s.daysUntilReset=t.daysUntilReset,s}return t}function tB({title:e,items:t,columns:s,onToggle:r}){return t.length?(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)("h4",{className:"text-sm font-medium",children:[e," ",(0,a.jsxs)("span",{className:"text-muted-foreground font-normal",children:["(",t.length,")"]})]}),(0,a.jsx)("div",{className:"overflow-x-auto rounded-md border",children:(0,a.jsxs)("table",{className:"w-full text-sm",children:[(0,a.jsx)("thead",{className:"bg-muted/50",children:(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{className:"p-2 text-left w-10",children:"選"}),s.map(e=>(0,a.jsx)("th",{className:"p-2 text-left whitespace-nowrap",children:e.label},String(e.key)))]})}),(0,a.jsx)("tbody",{children:t.map((e,t)=>(0,a.jsxs)("tr",{className:e.needsReview?"bg-amber-50 dark:bg-amber-950/30":void 0,children:[(0,a.jsx)("td",{className:"p-2",children:(0,a.jsx)(S.S,{checked:e.selected,onCheckedChange:e=>r(t,!0===e)})}),s.map(t=>(0,a.jsx)("td",{className:"p-2 whitespace-nowrap",children:t.render?t.render(e):String(e[t.key]??"")},String(t.key)))]},t))})]})})]}):null}function tL(){let{toast:e}=(0,t_.dj)(),t=(0,r.useRef)(null),[s,i]=(0,r.useState)("upload"),{loading:l,jobsLoading:n,error:c,limitInfo:o,analyzeResult:u,draft:m,commitResult:x,jobs:p,analyze:j,commit:v,refreshJobs:g,reset:y,toggleSelected:b}=function(){let{user:e}=(0,f.A)(),[t,s]=(0,r.useState)(!1),[a,i]=(0,r.useState)(!1),[l,n]=(0,r.useState)(null),[c,d]=(0,r.useState)(null),[o,u]=(0,r.useState)(null),[m,h]=(0,r.useState)(null),[x,p]=(0,r.useState)(null),[j,v]=(0,r.useState)([]),g=(0,r.useMemo)(()=>{if(!e)return null;async function t(){let t=await (async()=>e.getIdToken())();return{Authorization:`Bearer ${t}`}}return{async analyze(e){let s=new FormData;return s.append("file",e),tV(await fetch("/api/import/analyze",{method:"POST",headers:await t(),body:s}))},commit:async e=>tV(await fetch("/api/import/commit",{method:"POST",headers:{...await t(),"Content-Type":"application/json"},body:JSON.stringify(e)})),async listJobs(){let e=await fetch("/api/import/jobs",{headers:await t()});return(await tV(e)).jobs}}},[e]),y=(0,r.useCallback)(async e=>{if(!g)throw Error("請先登入");s(!0),n(null),d(null),p(null);try{let t=await g.analyze(e);return u(t),h(t.draft??null),t}catch(e){throw"DATA_IMPORT_LIMIT"===e.code&&null!=e.current&&null!=e.max&&d({current:e.current,max:e.max,daysUntilReset:e.daysUntilReset??30}),n(e.message||"分析失敗"),e}finally{s(!1)}},[g]),b=(0,r.useCallback)(async()=>{if(!g||!o?.jobId||!m)throw Error("請先完成分析");s(!0),n(null);try{let e={accounts:m.accounts.map(e=>e.selected),monthlyBalances:m.monthlyBalances.map(e=>e.selected),transactions:m.transactions.map(e=>e.selected),assets:m.assets.map(e=>e.selected),liabilities:m.liabilities.map(e=>e.selected),investments:m.investments.map(e=>e.selected),budgets:m.budgets.map(e=>e.selected),goals:m.goals.map(e=>e.selected)},t=await g.commit({jobId:o.jobId,selectionOverrides:e});return p(t),t}catch(e){throw n(e instanceof Error?e.message:"匯入失敗"),e}finally{s(!1)}},[g,o,m]),w=(0,r.useCallback)(async()=>
8{if(g){i(!0);try{let e=await g.listJobs();v(e)}catch{}finally{i(!1)}}},[g]);return{loading:t,jobsLoading:a,error:l,limitInfo:c,analyzeResult:o,draft:m,commitResult:x,jobs:j,analyze:y,commit:b,refreshJobs:w,reset:(0,r.useCallback)(()=>{u(null),h(null),p(null),n(null),d(null)},[]),toggleSelected:(0,r.useCallback)((e,t,s)=>{h(a=>{if(!a)return a;let r=[...a[e]],i=r[t];return i?(r[t]={...i,selected:s},{...a,[e]:r}):a})},[]),setDraft:h}}();(0,r.useEffect)(()=>{g()},[g]);let w=async t=>{if(t)try{await j(t),i("preview"),e({title:"分析完成",description:"請確認預覽資料後再匯入"})}catch{}},N=async()=>{try{let t=await v();i("done"),e({title:"匯入完成",description:`成功 ${t.imported}、略過 ${t.skipped}、失敗 ${t.failed}`}),g()}catch{}},k=()=>{y(),i("upload"),t.current&&(t.current.value="")};return(0,a.jsxs)("div",{className:"space-y-6",children:[(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(tP.A,{className:"h-5 w-5"}),"外部資料匯入"]}),(0,a.jsx)(d.BT,{children:"從 Google 試算表或 Excel 匯入帳戶、月收支、資產、負債、投資、預算與目標。 建議先下載官方範本整理資料;其他格式將由 AI 協助辨識。"})]}),(0,a.jsxs)(d.Wu,{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,a.jsx)(h.$,{variant:"outline",asChild:!0,children:(0,a.jsxs)("a",{href:"/templates/xynergy-data-import-template.xlsx",download:!0,children:[(0,a.jsx)(tD.A,{className:"h-4 w-4 mr-2"}),"下載官方範本"]})}),(0,a.jsx)(h.$,{variant:"ghost",asChild:!0,children:(0,a.jsx)(tv(),{href:"/help/guides/guide-data-import",target:"_blank",children:"使用說明"})})]}),o&&(0,a.jsxs)(e5.Fc,{variant:"destructive",children:[(0,a.jsx)(e5.XL,{children:"已達 30 天分析次數上限"}),(0,a.jsxs)(e5.TN,{children:["過去 30 天已使用 ",o.current," / ",o.max," 次分析。約"," ",o.daysUntilReset," 天後重置。"]})]}),c&&!o&&(0,a.jsxs)(e5.Fc,{variant:"destructive",children:[(0,a.jsx)(e5.XL,{children:"發生錯誤"}),(0,a.jsx)(e5.TN,{children:c})]}),"upload"===s&&(0,a.jsxs)("div",{className:"border border-dashed rounded-lg p-8 text-center space-y-4",children:[(0,a.jsx)(tF.A,{className:"h-10 w-10 mx-auto text-muted-foreground"}),(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"上傳 .xlsx / .xls / .csv(上限 2MB、5000 列)"}),(0,a.jsx)("input",{ref:t,type:"file",accept:".csv,.xlsx,.xls,text/csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel",className:"hidden",onChange:e=>void w(e.target.files?.[0])}),(0,a.jsx)(h.$,{disabled:l,onClick:()=>t.current?.click(),children:l?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eb.A,{className:"h-4 w-4 mr-2 animate-spin"}),"分析中…"]}):"選擇檔案"})]}),"preview"===s&&m&&u&&(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,a.jsx)(e4.E,{variant:"secondary",children:"official_template"===u.format?"官方範本":"AI 辨識"}),null!=u.confidence&&(0,a.jsxs)(e4.E,{variant:"outline",children:["信心 ",Math.round(100*u.confidence),"%"]})]}),u.warnings?.length>0&&(0,a.jsxs)(e5.Fc,{children:[(0,a.jsx)(e5.XL,{children:"注意"}),(0,a.jsx)(e5.TN,{children:(0,a.jsx)("ul",{className:"list-disc pl-4 space-y-1",children:u.warnings.map((e,t)=>(0,a.jsx)("li",{children:e},t))})})]}),(0,a.jsx)(tz,{draft:m,toggleSelected:b}),(0,a.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,a.jsx)(h.$,{variant:"outline",onClick:k,disabled:l,children:"重新上傳"}),(0,a.jsx)(h.$,{onClick:()=>void N(),disabled:l,children:l?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eb.A,{className:"h-4 w-4 mr-2 animate-spin"}),"匯入中…"]}):"確認匯入"})]})]}),"done"===s&&x&&(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsxs)(e5.Fc,{children:[(0,a.jsx)(e5.XL,{children:"匯入完成"}),(0,a.jsxs)(e5.TN,{children:["成功 ",x.imported," 筆、略過重複 ",x.skipped," 筆、失敗"," ",x.failed," 筆。重複資料不會覆寫既有內容。"]})]}),x.failed>0&&(0,a.jsx)("div",{className:"text-sm text-muted-foreground max-h-40 overflow-y-auto",children:x.details.filter(e=>"failed"===e.action).map((e,t)=>(0,a.jsxs)("div",{children:["[",e.entity,"] ",e.key,": ",e.message]},t))}),(0,a.jsx)(h.$,{onClick:k,children:"繼續匯入"})]})]})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsx)(d.ZB,{className:"text-base",children:"最近匯入紀錄"}),(0,a.jsx)(d.BT,{children:"顯示最近 10 次分析/匯入工作"})]}),(0,a.jsx)(d.Wu,{children:n?(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"載入中…"}):0===p.length?(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"尚無紀錄"}):(0,a.jsx)("ul",{className:"space-y-2 text-sm",children:p.map(e=>(0,a.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 border-b pb-2 last:border-0",children:[(0,a.jsx)("span",{className:"truncate max-w-[50%]",children:e.fileName}),(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)(e4.E,{variant:"outline",children:e.status}),e.commitResult&&(0,a.jsxs)("span",{className:"text-muted-foreground",children:["+",e.commitResult.imported," / skip ",e.commitResult.skipped]})]})]},e.id))})})]})]})}function tz({draft:e,toggleSelected:t}){return(0,a.jsxs)("div",{className:"space-y-6",children:[(0,a.jsx)(tB,{title:"帳戶",items:e.accounts,onToggle:(e,s)=>t("accounts",e,s),columns:[{key:"name",label:"名稱"},{key:"type",label:"類型"},{key:"category",label:"分類"},{key:"currency",label:"幣別"}]}),(0,a.jsx)(tB,{title:"月收支",items:e.monthlyBalances,onToggle:(e,s)=>t("monthlyBalances",e,s),columns:[{key:"accountName",label:"帳戶"},{key:"month",label:"月份"},{key:"balance",label:"金額"}]}),(0,a.jsx)(tB,{title:"資產",items:e.assets,onToggle:(e,s)=>t("assets",e,s),columns:[{key:"name",label:"名稱"},{key:"type",label:"類型"},{key:"value",label:"現值"}]}),(0,a.jsx)(tB,{title:"負債",items:e.liabilities,onToggle:(e,s)=>t("liabilities",e,s),columns:[{key:"name",label:"名稱"},{key:"type",label:"類型"},{key:"value",label:"餘額"}]}),(0,a.jsx)(tB,{title:"投資",items:e.investments,onToggle:(e,s)=>t("investments",e,s),columns:[{key:"name",label:"標的"},{key:"symbol",label:"代號"},{key:"quantity",label:"數量"},{key:"price",label:"價格"}]}),(0,a.jsx)(tB,{title:"預算",items:e.budgets,onToggle:(e,s)=>t("budgets",e,s),columns:[{key:"year",label:"年度"},{key:"totalIncome",label:"總收入"},{key:"categories",label:"分類數",render:e=>String(e.categories?.length??0)}]}),(0,a.jsx)(tB,{title:"目標",items:e.goals,onToggle:(e,s)=>t("goals",e,s),columns:[{key:"name",label:"名稱"},{key:"type",label:"類型"},{key:"targetAmount",label:"目標金額"},{key:"deadline",label:"期限",render:e=>`${e.deadlineYear}-${String(e.deadlineMonth).padStart(2,"0")}`}]})]})}var tO=s(78139),tU=s(26345),tM=s(60373),tW=s(97839),tZ=s(21582),tH=s(83392),tJ=s(24385),tG=s(81321),tY=s(63533),tq=s(80746),tX=s(66592),tK=s(3953);let tQ={never:"無期限","1d":"1 天","3d":"3 天","7d":"7 天","1mo":"1 個月(30 天)",custom:"自訂日期"};function t0(e){return e instanceof Date&&!Number.isNaN(e.getTime())}function t1({presetName:e,customDateName:t,timeName:s,disabled:i}){let{control:l,setValue:c,getValues:d}=(0,n.xW)(),[u,m]=(0,r.useState)(!1),p=(0,n.FH)({control:l,name:e});return(0,r.useEffect)(()=>{"custom"!==p||t0(d(t))||c(t,new Date)},[p,t,d,c]),(0,a.jsx)(x.zB,{control:l,name:e,render:({field:e})=>(0,a.jsxs)(x.eI,{className:"space-y-3",children:[(0,a.jsx)(x.lR,{className:"text-sm font-medium",children:"有效期限"}),(0,a.jsxs)(tZ.l6,{value:e.value,disabled:i,onValueChange:t=>{e.onChange(t),"custom"===t&&m(!0)},children:[(0,a.jsx)(x.MJ,{children:(0,a.jsx)(tZ.bq,{className:"w-full",children:(0,a.jsx)(tZ.yv,{placeholder:"選擇有效期限"})})}),(0,a.jsx)(tZ.gC,{children:Object.keys(tQ).map(e=>(0,a.jsx)(tZ.eb,{value:e,children:tQ[e]},e))})]}),"custom"===p?(0,a.jsxs)("div",{className:"flex flex-col gap-3 rounded-md border border-border bg-muted/20 p-3 sm:flex-row sm:items-end",children:[(0,a.jsx)(x.zB,{control:l,name:t,render:({field:e})=>(0,a.jsxs)(x.eI,{className:"flex flex-1 flex-col gap-2",children:[(0,a.jsx)("span",{className:"text-xs text-muted-foreground",children:"日期"}),(0,a.jsxs)(tK.AM,{open:u,onOpenChange:m,children:[(0,a.jsx)(tK.Wv,{asChild:!0,children:(0,a.jsxs)(h.$,{type:"button",variant:"outline",disabled:i,className:(0,eA.cn)("w-full justify-start gap-2 font-normal"),children:[(0,a.jsx)(tY.A,{className:"h-4 w-4 shrink-0 opacity-70","aria-hidden":!0}),t0(e.value)?(0,tJ.GP)(e.value,"yyyy / MM / dd"):"選擇日期"]})}),(0,a.jsx)(tK.hl,{className:"w-auto p-0",align:"start",children:(0,a.jsx)(tX.V,{mode:"single",locale:tq.G,selected:t0(e.value)?e.value:void 0,onSelect:t=>{t&&e.onChange(t)}
8,defaultMonth:t0(e.value)?e.value:new Date})})]}),(0,a.jsx)(x.C5,{})]})}),(0,a.jsx)(x.zB,{control:l,name:s,render:({field:e})=>(0,a.jsxs)(x.eI,{className:"flex w-full flex-col gap-2 sm:w-[8.5rem]",children:[(0,a.jsx)("span",{className:"text-xs text-muted-foreground",children:"時間"}),(0,a.jsx)(x.MJ,{children:(0,a.jsx)(o.p,{type:"time",disabled:i,className:"w-full",...e})}),(0,a.jsx)(x.C5,{})]})})]}):null,(0,a.jsx)(x.C5,{})]})})}let t2=I.Ik({expiryPreset:tH.l7,customExpiryDate:I.bz().optional(),customExpiryTime:I.Yj().optional()}).superRefine((e,t)=>{if("custom"!==e.expiryPreset)return;let s=e.customExpiryDate;(!s||!(s instanceof Date)||Number.isNaN(s.getTime()))&&t.addIssue({code:tG.eq.custom,message:"請選擇日期",path:["customExpiryDate"]});let a=(e.customExpiryTime??"").trim();/^\d{2}:\d{2}$/.test(a)||t.addIssue({code:tG.eq.custom,message:"請輸入有效時間",path:["customExpiryTime"]})});function t3(e){if(!e.expiresAt)return{expiryPreset:"never",customExpiryDate:new Date,customExpiryTime:"23:59"};let t=new Date(e.expiresAt);return Number.isFinite(t.getTime())?{expiryPreset:"custom",customExpiryDate:t,customExpiryTime:(0,tJ.GP)(t,"HH:mm")}:{expiryPreset:"never",customExpiryDate:new Date,customExpiryTime:"23:59"}}function t4({open:e,onOpenChange:t,share:s,saving:i,onSave:l}){let d=(0,n.mN)({resolver:(0,c.u)(t2),defaultValues:t3(s??{id:"",recipientUid:"",resourceKey:"",permission:"view"})});(0,r.useEffect)(()=>{e&&s&&d.reset(t3(s))},[e,s,d]);let o=(()=>{if(!s)return"";let e=tH.k3.safeParse(s.resourceKey);return e.success?(0,tH.pu)(e.data):s.resourceKey})(),u=d.handleSubmit(async e=>{if(!s)return;let a="never"===e.expiryPreset?null:(0,tH.wr)(e.expiryPreset,{date:e.customExpiryDate,time:e.customExpiryTime??"23:59"});("never"===e.expiryPreset||a)&&(await l(s.id,a??null),t(!1))});return(0,a.jsx)(A.lG,{open:e,onOpenChange:t,children:(0,a.jsxs)(A.Cf,{className:"sm:max-w-md",children:[(0,a.jsxs)(A.c7,{children:[(0,a.jsx)(A.L3,{children:"修改有效期限"}),(0,a.jsx)(A.rr,{children:o?`「${o}」的分享期限`:"調整此筆分享的有效期限"})]}),(0,a.jsx)(x.lV,{...d,children:(0,a.jsxs)("form",{onSubmit:e=>void u(e),className:"space-y-4",children:[(0,a.jsx)(t1,{presetName:"expiryPreset",customDateName:"customExpiryDate",timeName:"customExpiryTime",disabled:i}),(0,a.jsxs)(A.Es,{className:"gap-2 sm:gap-0",children:[(0,a.jsx)(h.$,{type:"button",variant:"outline",disabled:i,onClick:()=>t(!1),children:"取消"}),(0,a.jsx)(h.$,{type:"submit",disabled:i,children:i?"儲存中…":"儲存"})]})]})})]})})}function t5(e){let t=tH.k3.safeParse(e);return t.success?tH.tc[t.data]?.label??e:e}function t6(e){let t=tH.k3.safeParse(e);if(!t.success)return 999;let s=tH.kc.indexOf(t.data);return s>=0?s:999}function t8(e){if(!e.createdAt)return 0;let t=Date.parse(e.createdAt);return Number.isFinite(t)?t:0}function t7(e){return"edit"===e?"可編輯":"僅檢視"}let t9="grid grid-cols-1 items-center gap-3 sm:grid-cols-[minmax(0,1fr)_minmax(9rem,11rem)_minmax(9rem,11rem)] sm:gap-4";function se({title:e,subtitle:t}){return(0,a.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,a.jsx)(tM.eu,{className:"h-9 w-9 shrink-0",children:(0,a.jsx)(tM.q5,{className:"text-xs",children:function(e){let t=e.trim();if(!t)return"?";let s=t.split(/\s+/).filter(Boolean);return s.length>=2?(s[0][0]+s[1][0]).toUpperCase():t.slice(0,2).toUpperCase()}(e)})}),(0,a.jsxs)("div",{className:"min-w-0",children:[(0,a.jsx)("p",{className:"truncate font-medium",children:e}),t&&t!==e?(0,a.jsx)("p",{className:"truncate text-xs text-muted-foreground",children:t}):null]})]})}function st({group:e,selectedGrantId:t,onSelectGrant:s}){let r=e.grants.find(e=>e.id===t)??e.grants[0]??null,i=r?t5(r.resourceKey):"選擇頁面";return(0,a.jsxs)(tW.rI,{children:[(0,a.jsx)(tW.ty,{asChild:!0,children:(0,a.jsxs)(h.$,{variant:"outline",className:"h-9 w-full justify-between gap-1 px-3 font-normal",children:[(0,a.jsx)("span",{className:"truncate",children:i}),(0,a.jsx)(tU.A,{className:"size-4 shrink-0 opacity-60","aria-hidden":!0})]})}),(0,a.jsx)(tW.SQ,{align:"start",className:"min-w-[var(--radix-dropdown-menu-trigger-width)]",children:e.grants.map(e=>(0,a.jsx)(tW._2,{className:"cursor-pointer",onClick:()=>s(e),children:t5(e.resourceKey)},e.id))})]})}function ss({group:e,direction:t,onRevoke:s,onDismiss:l,onPermissionChange:n,onExpiryChange:c,permissionUpdatingShareId:d,dism
8issingShareId:o}){let u=function(){let e=(0,i.useRouter)(),{setViewingUser:t}=(0,f.A)(),{toast:s}=(0,p.dj)();return(0,r.useCallback)((a,r,i)=>{let l=tH.k3.safeParse(i);if(!l.success)return void s({title:"無法開啟",description:"此分享資源已失效或不受支援",variant:"destructive"});let n=l.data,c=tH.tc[n]?.dashboardPath;if(!c)return void s({title:"無法開啟",description:"找不到對應頁面",variant:"destructive"});let d=r?.trim()||a;t(a,d),e.push(c),s({title:"已開啟分享內容",description:`正在檢視「${(0,tH.pu)(n)}」\xb7 ${d}`})},[e,t,s])}(),[m,x]=(0,r.useState)(e.grants[0]?.id??""),[j,v]=(0,r.useState)(!1);(0,r.useEffect)(()=>{!e.grants.length||e.grants.some(e=>e.id===m)||x(e.grants[0].id)},[e.grants,m]);let g=e.grants.find(e=>e.id===m)??e.grants[0]??null,y=1===e.grants.length?t5(e.grants[0].resourceKey):`${e.grants.length} 頁`,b="outbound"===t&&!!n&&!!g,w=!!g&&d===g.id,N=!!g&&o===g.id;return(0,a.jsxs)("div",{className:(0,eA.cn)(t9,"px-4 py-3"),children:[(0,a.jsx)(se,{title:e.title,subtitle:e.subtitle}),"inbound"===t?(0,a.jsx)(st,{group:e,selectedGrantId:m,onSelectGrant:e=>{x(e.id),e.ownerId&&u(e.ownerId,e.ownerLabel??e.ownerEmail,e.resourceKey)}}):(0,a.jsxs)(tZ.l6,{value:m,onValueChange:x,children:[(0,a.jsx)(tZ.bq,{className:"h-9 w-full","aria-label":"選擇存取的頁面",children:(0,a.jsx)(tZ.yv,{placeholder:"選擇頁面",children:y})}),(0,a.jsx)(tZ.gC,{children:e.grants.map(e=>(0,a.jsx)(tZ.eb,{value:e.id,children:t5(e.resourceKey)},e.id))})]}),"inbound"===t&&l&&g?(0,a.jsx)(h.$,{type:"button",variant:"outline",className:"h-9 w-full text-destructive hover:text-destructive",disabled:N,onClick:()=>l(g.id),children:"移除"}):b&&g?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(tW.rI,{children:[(0,a.jsx)(tW.ty,{asChild:!0,disabled:w,children:(0,a.jsxs)(h.$,{variant:"outline",className:"h-9 w-full justify-between gap-1 px-3 font-normal",children:[(0,a.jsx)("span",{className:"truncate",children:t7(g.permission)}),(0,a.jsx)(tU.A,{className:"size-4 shrink-0 opacity-60","aria-hidden":!0})]})}),(0,a.jsxs)(tW.SQ,{align:"end",className:"w-44",children:[(0,a.jsx)(tW.lp,{children:"存取權限"}),(0,a.jsx)(tW._2,{disabled:"view"===g.permission||w,onClick:()=>n?.(g.id,"view"),children:"僅檢視"}),(0,a.jsx)(tW._2,{disabled:"edit"===g.permission||w,onClick:()=>n?.(g.id,"edit"),children:"可編輯"}),c?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(tW.mB,{}),(0,a.jsx)(tW._2,{disabled:w,onClick:()=>v(!0),children:"修改期限"})]}):null,s?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(tW.mB,{}),(0,a.jsx)(tW._2,{className:"text-destructive focus:text-destructive",onClick:()=>s(g.id),children:"撤銷分享"})]}):null]})]}),c?(0,a.jsx)(t4,{open:j,onOpenChange:v,share:g,saving:w,onSave:c}):null]}):(0,a.jsx)("div",{className:"flex h-9 w-full items-center rounded-md border border-input bg-muted/30 px-3 text-sm text-muted-foreground",children:g?t7(g.permission):"—"})]})}function sa({shares:e,direction:t,onRevoke:s,onDismiss:i,onPermissionChange:l,onExpiryChange:n,permissionUpdatingShareId:c,dismissingShareId:d}){let o=(0,r.useMemo)(()=>{let s=new Map;for(let a of e){let e="outbound"===t?a.recipientUid||null:a.ownerId||null;if(!e)continue;let r=s.get(e),i="outbound"===t?a.recipientLabel?.trim()||a.recipientUid:a.ownerLabel?.trim()||a.ownerId||a.recipientUid,l="outbound"===t?a.recipientEmail??a.recipientUid:a.ownerEmail??a.ownerId??"",n=t8(a);r?(r.grants.push(a),n>r.sortMs&&(r.sortMs=n)):s.set(e,{key:e,title:i,subtitle:l,grants:[a],sortMs:n})}for(let e of s.values())e.grants.sort((e,t)=>t6(e.resourceKey)-t6(t.resourceKey)||t8(t)-t8(e));return[...s.values()].sort((e,t)=>t.sortMs-e.sortMs||e.title.localeCompare(t.title,"zh-TW"))},[e,t]);return o.length?(0,a.jsxs)("div",{className:"overflow-hidden rounded-lg border",children:[(0,a.jsxs)("div",{className:(0,eA.cn)("hidden border-b bg-muted/30 px-4 py-2 text-xs font-medium text-muted-foreground sm:grid",t9),children:[(0,a.jsx)("span",{children:"使用者"}),(0,a.jsx)("span",{children:"存取的頁面"}),(0,a.jsx)("span",{children:"inbound"===t?"操作":"存取權限"})]}),(0,a.jsx)("ul",{children:o.map(e=>(0,a.jsx)("li",{className:"border-b last:border-b-0",children:(0,a.jsx)(ss,{group:e,direction:t,onRevoke:s,onDismiss:i,onPermissionChange:l,onExpiryChange:n,permissionUpdatingShareId:c,dismissingShareId:d})},e.key))})]}):null}var sr=s(54306);function si(){let{activeOutbound:e,activeInbound:t,loading:s,revokeShare:r,dismissInboundShare:i,updateSharePermission:l,updateShareExpiry:n,permissionUpdatingShareId:c,dismissingShareId:o}=(0,tO.m)(),u=e.length>0,m=t.length>0;return(0,a.jsx)("div",{className:"w-full space-y-6",children:(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsx)(d.ZB,{children:"資料分享"}),(0,a.jsx)(d.BT,{children:"新增分享請至各功能頁頂欄的分享圖示;此處可檢視與管理已建立的授權。列表依對象用戶分組。"})]}),(0,a.jsxs)(d.Wu,{className:"space-y-8",children:[u||m?null:s?(0,a.jsx)(sr.default,{size:40}):(0,a.jsx)("p",{className:"text-sm text-muted-foreground",children:"目前沒有任何有效分享"}),u?(0,a.jsxs)("section",{className:"space-y-3",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-semibold",children:"我分享的資料"}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"可調整權限、有效期限或撤銷分享。"})]}),(0,a.jsx)(sa,{shares:e,direction:"outbound",onRevoke:e=>void r(e),onPermissionChange:(e,t)=>
8void l(e,t),onExpiryChange:(e,t)=>n(e,t),permissionUpdatingShareId:c})]}):null,m?(0,a.jsxs)("section",{className:"space-y-3",children:[(0,a.jsxs)("div",{children:[(0,a.jsx)("h3",{className:"text-sm font-semibold",children:"與我分享的資料"}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground",children:"點「存取的頁面」中的頁面名稱即可開啟檢視;「移除」僅從您的清單隱藏,不影響分享者的授權。"})]}),(0,a.jsx)(sa,{shares:t,direction:"inbound",onDismiss:e=>void i(e),dismissingShareId:o})]}):null]})]})})}var sl=s(27012),sn=s(57663),sc=s(35617);let sd=I.Ik({error:I.bz()});async function so(e){try{let t=await e.json(),s=sd.safeParse(t);if(!s.success)return`HTTP ${e.status}`;let a=s.data.error;if("string"==typeof a)return a;return`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}let su=I.Ik({email:I.Yj().nullable().optional(),displayName:I.Yj().nullable().optional(),referralCode:I.Yj().nullable().optional()}),sm=I.Ik({id:I.Yj(),advisorId:I.Yj().nullable().optional(),userId:I.Yj(),consentId:I.Yj().nullable().optional(),isActive:I.zM(),relationshipOnly:I.zM().optional(),sharePermission:I.k5(["view","edit"]).nullable().optional(),relationshipActive:I.zM().optional(),authorizedAt:I.Yj().nullable().optional(),createdAt:I.Yj().nullable().optional(),updatedAt:I.Yj().nullable().optional(),user:su.nullable().optional()}),sh=I.Ik({clients:I.YO(sm)});function sx(){let{user:e,loading:t}=(0,f.A)(),[s,a]=(0,r.useState)(!1),[i,l]=(0,r.useState)([]),[n,c]=(0,r.useState)(!1),[d,o]=(0,r.useState)(null),u=(0,r.useCallback)(async()=>{if(e){c(!0),o(null);try{let t=await e.getIdToken(),a=new URLSearchParams;s&&a.set("includeInactive","true");let r=await fetch(`/api/advisor/clients?${a.toString()}`,{method:"GET",headers:{...{Authorization:`Bearer ${t}`}}});if(!r.ok)throw Error(await so(r));let i=await r.json(),n=sh.safeParse(i);if(!n.success)throw Error("回應格式錯誤");l(n.data.clients)}catch(e){o(e instanceof Error?e.message:"載入失敗"),l([])}finally{c(!1)}}},[e,s]);(0,r.useEffect)(()=>{t||e&&u()},[t,e,u]);let m=(0,r.useMemo)(()=>i.filter(e=>e.isActive).length,[i]);return{includeInactive:s,setIncludeInactive:a,clients:i,activeCount:m,isLoading:n,error:d,reload:u}}let sp=I.Ik({error:I.bz()});async function sf(e){try{let t=await e.json(),s=sp.safeParse(t);if(!s.success)return`HTTP ${e.status}`;let a=s.data.error;if("string"==typeof a)return a;return`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function sj(e){return{Authorization:`Bearer ${e}`}}let sv=I.Ik({source:I.k5(["retirement","insurance","other"]),entry:I.Yj(),summary:I.Yj(),riskLevel:I.Yj().optional(),category:I.Yj().optional()}).optional().nullable(),sg=I.Ik({id:I.Yj(),status:I.Yj(),date:I.Yj().optional().nullable(),time:I.Yj().optional().nullable(),topic:I.Yj().optional().nullable(),method:I.Yj().optional().nullable(),userId:I.Yj().optional().nullable(),userEmail:I.Yj().optional().nullable(),userDisplayName:I.Yj().optional().nullable(),advisorFee:I.ai().optional().nullable(),paymentAmount:I.ai().optional().nullable(),paymentType:I.Yj().optional().nullable(),paymentReference:I.Yj().optional().nullable(),cancellationReason:I.Yj().optional().nullable(),bookingContext:sv,createdAt:I.bz().optional(),updatedAt:I.bz().optional()}).passthrough(),sy=I.Ik({bookings:I.YO(sg)});function sb(){let{user:e,loading:t}=(0,f.A)(),[s,a]=(0,r.useState)("all"),[i,l]=(0,r.useState)(""),[n,c]=(0,r.useState)(""),[d,o]=(0,r.useState)(""),[u,m]=(0,r.useState)([]),[h,x]=(0,r.useState)(!1),[p,j]=(0,r.useState)(null),v=(0,r.useCallback)(async()=>{if(e){x(!0),j(null);try{let t=await e.getIdToken(),a=new URLSearchParams;s&&"all"!==s&&a.set("status",s),i&&a.set("startDate",i),n&&a.set("endDate",n),a.set("limit","100");let r=await fetch(`/api/advisor/bookings?${a.toString()}`,{method:"GET",headers:{...sj(t)}});if(!r.ok)throw Error(await sf(r));let l=await r.json(),c=sy.safeParse(l);if(!c.success)throw Error("回應格式錯誤");m(c.data.bookings)}catch(e){j(e instanceof Error?e.message:"載入失敗"),m([])}finally{x(!1)}}},[e,s,i,n]);(0,r.useEffect)(()=>{t||e&&v()},[t,e,v]);let g=(0,r.useMemo)(()=>{let e=d.trim().toLowerCase();return e?u.filter(t=>{let s=String(t.userEmail||"").toLowerCase(),a=String(t.userDisplayName||"").toLowerCase(),r=String(t.topic||"").toLowerCase();return s.includes(e)||a.includes(e)||r.includes(e)||String(t.id).toLowerCase().includes(e)}):u},[u,d]);return{status:s,setStatus:a,startDate:i,setStartDate:l,endDate:n,setEndDate:c,keyword:d,setKeyword:o,bookings:g,rawBookings:u,isLoading:h,error:p,reload:v,cancelBooking:(0,r.useCallback)(async(t,s)=>{if(!e||!t)return;let a=await e.getIdToken(),r=await fetch(`/api/advisor/bookings/${encodeURIComponent(t)}/cancel`,{method:"POST",headers:{"Content-Type":"application/json",...sj(a)},body:JSON.stringify({reason:s})});if(!r.ok)throw Error(await sf(r));await r.json().catch(()=>({})),m(e=>e.map(e=>e.id===t?{...e,status:"cancelled",cancellationReason:s||e.cancellationReason||""}:e))},[e])}}let sw=I.Ik({error:I.bz()});async function sN(e){try{let t=await e.json(),s=sw.safeParse(t);if(!s.success)return`HTTP ${e.status}`;let a=s.data.error;if("string"==typeof a)return a;return`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function sk(e){return{Authorization:`Bearer ${e}`}}let sC=I.Ik({totalRevenue:I.ai(),totalPlatformFee:I.ai(),totalAdvisorRevenue:I.ai(),transactionCount:I.ai().int()}),sA=I.Ik({bookingId:I.Yj(),date:I.Yj().nullable().optional(),time:I.Yj().nullable().optional(),userId:I.Yj().nullable().optional(),userEmail:I.Yj().nullable().optional(),userDisplayName:I.Yj().nullable().optional(),amount:I.ai(),platformFee:I.ai(),advisorRevenue:I.ai(),paymentReference:I.Yj().nullable().optional(),paymentType:I.Yj().nullable().optional()}).passthrough(),sS=I.Ik({summary:sC,items:I.YO(sA)});function sE(){let{user:e,loading:t}=(0,f.A)(),[s,a]=(0,r.useState)(""),[i,l]=(0,r.useState)(""),[n,c]=(0,r.useState)(null),[d,o]=(0,r.useState)([]),[u,m]=(0,r.useState)(!1),[h,x]=(0,r.useState)(null),p=(0,r.useCallback)(async()=>
8{if(e){m(!0),x(null);try{let t=await e.getIdToken(),a=new URLSearchParams;s&&a.set("startDate",s),i&&a.set("endDate",i);let r=await fetch(`/api/advisor/revenue?${a.toString()}`,{method:"GET",headers:{...sk(t)}});if(!r.ok)throw Error(await sN(r));let l=await r.json(),n=sS.safeParse(l);if(!n.success)throw Error("回應格式錯誤");c(n.data.summary),o(n.data.items)}catch(e){x(e instanceof Error?e.message:"載入失敗"),c(null),o([])}finally{m(!1)}}},[e,s,i]);(0,r.useEffect)(()=>{t||e&&p()},[t,e,p]);let j=(0,r.useCallback)(async()=>{if(!e)return;let t=await e.getIdToken(),a=new URLSearchParams;s&&a.set("startDate",s),i&&a.set("endDate",i);let r=await fetch(`/api/advisor/revenue/export?${a.toString()}`,{method:"GET",headers:{...sk(t)}});if(!r.ok)throw Error(await sN(r));let l=await r.blob(),n=URL.createObjectURL(l),c=document.createElement("a");c.href=n,c.download="advisor-revenue.csv",c.click(),URL.revokeObjectURL(n)},[e,s,i]);return{startDate:s,setStartDate:a,endDate:i,setEndDate:l,summary:n,items:d,isLoading:u,error:h,reload:p,exportCsv:j}}var sI=s(17938);function sR(){let{toast:e}=(0,p.dj)(),{clients:t,activeCount:s,isLoading:i}=sx(),{rawBookings:l,isLoading:n}=sb(),{summary:c,isLoading:m}=sE(),{withdrawals:x,summary:j,loading:v,error:g,hasMore:y,loadMore:b,refresh:w,createWithdrawal:N}=function(e=20){let{user:t}=(0,f.A)(),[s,a]=(0,r.useState)([]),[i,l]=(0,r.useState)({totalRevenue:0,totalConsultationRevenue:0,totalWithdrawn:0,availableAmount:0}),[n,c]=(0,r.useState)(!1),[d,o]=(0,r.useState)(null),[u,m]=(0,r.useState)(null),[h,x]=(0,r.useState)(!1),p=(0,r.useCallback)(async(s=!1,r=null)=>{if(t)try{c(!0),o(null);let i=await t.getIdToken(),n=new URLSearchParams({limit:e.toString()});!s&&r&&n.set("cursor",r);let d=await fetch(`/api/advisor/withdrawals?${n.toString()}`,{headers:{Authorization:`Bearer ${i}`}});if(!d.ok){let e=await d.json();throw Error(e.error||"載入失敗")}let u=await d.json();s?a(u.withdrawals):a(e=>[...e,...u.withdrawals]),m(u.pagination.cursor),l(u.summary),x(u.pagination.hasMore)}catch(e){o(e.message||"載入提領記錄失敗")}finally{c(!1)}},[t,e]);(0,r.useEffect)(()=>{p(!0,null)},[t,p]);let j=(0,r.useCallback)(()=>{!n&&h&&u&&p(!1,u)},[n,h,u,p]),v=(0,r.useCallback)(()=>{m(null),a([]),p(!0,null)},[p]),g=(0,r.useCallback)(async e=>{if(!t)throw Error("請先登入");let s=await t.getIdToken(),a=await fetch("/api/advisor/withdrawals",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({amount:e.amount,bankName:e.bankName,accountNumber:e.accountNumber,accountHolder:e.accountHolder})});if(!a.ok)throw Error((await a.json()).error||"提交失敗");await v()},[t,v]);return{withdrawals:s,summary:i,loading:n,error:d,hasMore:h,loadMore:j,refresh:v,createWithdrawal:g}}(10),[k,C]=(0,r.useState)(!1),[A,S]=(0,r.useState)(""),[E,I]=(0,r.useState)(""),[R,T]=(0,r.useState)(""),[$,P]=(0,r.useState)(""),[D,F]=(0,r.useState)(!1),_=(0,r.useMemo)(()=>{let e=l.reduce((e,t)=>{let s=String(t.status||"unknown");return e[s]=(e[s]||0)+1,e},{});return{total:l.length,pending:e.pending||0,authorized:e.authorized||0,paid:e.paid||0,cancelled:e.cancelled||0}},[l]),V=async()=>{if(D)return;let t=parseFloat(A);if(!t||t<300||t>j.availableAmount)return void e({title:"金額錯誤",description:`提領金額必須在 NT$ 300 到 NT$ ${j.availableAmount.toLocaleString("zh-TW",{minimumFractionDigits:2,maximumFractionDigits:2})} 之間`,variant:"destructive"});if(!E.trim()||!R.trim()||!$.trim())return void e({title:"資料不完整",description:"請填寫完整的銀行帳戶資訊",variant:"destructive"});try{F(!0),await N({amount:t,bankName:E.trim(),accountNumber:R.trim(),accountHolder:$.trim()}),C(!1),S(""),I(""),T(""),P(""),e({title:"申請已提交",description:"提領申請已提交,等待管理員審核"})}catch(t){e({title:"提交失敗",description:t.message||"無法提交提領申請",variant:"destructive"})}finally{F(!1)}};return(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-3",children:[(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsx)(d.ZB,{className:"text-base",children:"客戶"})}),(0,a.jsxs)(d.Wu,{className:"space-y-2",children:[(0,a.jsx)("div",{className:"text-2xl font-semibold",children:i?"—":s}),(0,a.jsxs)("div",{className:"text-sm text-muted-foreground",children:["啟用客戶 / 總數 ",i?"—":t.length]})]})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsx)(d.ZB,{className:"text-base",children:"預約"})}),(0,a.jsxs)(d.Wu,{className:"space-y-2",children:[(0,a.jsx)("div",{className:"text-2xl font-semibold",children:n?"—":_.total}),(0,a.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,a.jsxs)(e4.E,{variant:"outline",children:["待授權 ",n?"—":_.pending]}),(0,a.jsxs)(e4.E,{variant:"secondary",children:["已授權 ",n?"—":_.authorized]}),(0,a.jsxs)(e4.E,{variant:"default",children:["已付款 ",n?"—":_.paid]}),(0,a.jsxs)(e4.E,{variant:"destructive",children:["已取消 ",n?"—":_.cancelled]})]})]})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsx)(d.ZB,{className:"text-base",children:"收入(已付款)"})}),(0,a.jsxs)(d.Wu,{className:"space-y-2",children:[(0,a.jsx)("div",{className:"text-2xl font-semibold",children:m||!c?"—":(0,sc.C)(c.totalAdvisorRevenue,{showSymbol:!0})}),(0,a.jsx)("div",{className:"text-sm text-muted-foreground",children:m||!c?"—":`總收入 ${(0,sc.C
8)(c.totalRevenue,{showSymbol:!0})},平台費 ${(0,sc.C)(c.totalPlatformFee,{showSymbol:!0})}`})]})]})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsxs)("div",{children:[(0,a.jsxs)(d.ZB,{className:"flex items-center gap-2",children:[(0,a.jsx)(sI.A,{className:"h-5 w-5"}),"提領申請"]}),(0,a.jsx)(d.BT,{children:"申請提領您的諮詢收入,管理員審核後將匯款至指定銀行帳戶"})]}),!k&&j.availableAmount>=300&&(0,a.jsx)(h.$,{onClick:()=>C(!0),disabled:v,children:"申請提領"})]})}),(0,a.jsxs)(d.Wu,{children:[(0,a.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-3 mb-4",children:[(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{className:"pb-2",children:(0,a.jsx)(d.ZB,{className:"text-sm font-medium",children:"總收入"})}),(0,a.jsxs)(d.Wu,{children:[v?(0,a.jsx)(sn.E,{className:"h-8 w-24"}):(0,a.jsx)("div",{className:"text-xl font-bold",children:(0,sc.C)(j.totalRevenue,{showSymbol:!0})}),(0,a.jsx)("p",{className:"text-xs text-muted-foreground mt-1",children:"已完成的付費諮詢"})]})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{className:"pb-2",children:(0,a.jsx)(d.ZB,{className:"text-sm font-medium",children:"諮詢收入"})}),(0,a.jsx)(d.Wu,{children:v?(0,a.jsx)(sn.E,{className:"h-8 w-24"}):(0,a.jsx)("div",{className:"text-xl font-bold",children:(0,sc.C)(j.totalConsultationRevenue,{showSymbol:!0})})})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{className:"pb-2",children:(0,a.jsx)(d.ZB,{className:"text-sm font-medium",children:"已提領金額"})}),(0,a.jsx)(d.Wu,{children:v?(0,a.jsx)(sn.E,{className:"h-8 w-24"}):(0,a.jsx)("div",{className:"text-xl font-bold",children:(0,sc.C)(j.totalWithdrawn,{showSymbol:!0})})})]}),(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{className:"pb-2",children:(0,a.jsx)(d.ZB,{className:"text-sm font-medium",children:"可提領金額"})}),(0,a.jsx)(d.Wu,{children:v?(0,a.jsx)(sn.E,{className:"h-8 w-24"}):(0,a.jsx)("div",{className:"text-xl font-bold text-green-600",children:(0,sc.C)(j.availableAmount,{showSymbol:!0})})})]})]}),g&&(0,a.jsx)(e5.Fc,{variant:"destructive",className:"mb-4",children:(0,a.jsx)(e5.TN,{children:g})}),k&&(0,a.jsxs)("div",{className:"space-y-4 mb-6 p-4 rounded-lg border border-border bg-muted/50",children:[(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"withdrawal-amount",children:"提領金額"}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(o.p,{id:"withdrawal-amount",type:"number",min:"300",max:j.availableAmount,step:"0.01",value:A,onChange:e=>S(e.target.value),placeholder:`最低 NT$ 300,最高 ${(0,sc.C)(j.availableAmount,{showSymbol:!0})}`}),(0,a.jsxs)("p",{className:"text-xs text-muted-foreground",children:["可提領金額:",(0,sc.C)(j.availableAmount,{showSymbol:!0})]})]})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"bank-name",children:"銀行名稱"}),(0,a.jsx)(o.p,{id:"bank-name",value:E,onChange:e=>I(e.target.value),placeholder:"例如:台灣銀行"})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"account-number",children:"帳號"}),(0,a.jsx)(o.p,{id:"account-number",value:R,onChange:e=>T(e.target.value),placeholder:"請輸入銀行帳號"})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{htmlFor:"account-holder",children:"戶名"}),(0,a.jsx)(o.p,{id:"account-holder",value:$,onChange:e=>P(e.target.value),placeholder:"請輸入帳戶持有人姓名"})]}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)(h.$,{onClick:V,disabled:D,className:"flex-1",children:D?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eb.A,{className:"h-4 w-4 mr-2 animate-spin"}),"提交中..."]}):"提交申請"}),(0,a.jsx)(h.$,{variant:"outline",onClick:()=>{C(!1),S(""),I(""),T(""),P("")},children:"取消"})]})]}),v&&0===x.length?(0,a.jsx)("div",{className:"space-y-2",children:Array.from({length:3}).map((e,t)=>(0,a.jsx)(sn.E,{className:"h-16 w-full"},t))}):0===x.length?(0,a.jsx)("div",{className:"text-center py-8 text-muted-foreground",children:j.availableAmou
8nt<300?(0,a.jsx)("p",{children:"可提領金額不足(最低 NT$ 300)"}):(0,a.jsx)("p",{children:"尚無提領記錄"})}):(0,a.jsxs)("div",{className:"space-y-2",children:[x.map(e=>(0,a.jsx)("div",{className:"flex items-center justify-between p-4 rounded-lg border border-border",children:(0,a.jsxs)("div",{className:"flex-1",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)("div",{className:"font-semibold",children:(0,sc.C)(e.amount,{showSymbol:!0})}),(0,a.jsxs)(e4.E,{variant:"completed"===e.status?"default":"approved"===e.status?"secondary":"rejected"===e.status?"destructive":"outline",children:["pending"===e.status&&"待審核","approved"===e.status&&"已核准","rejected"===e.status&&"已拒絕","completed"===e.status&&"已完成"]})]}),(0,a.jsxs)("div",{className:"text-sm text-muted-foreground mt-1",children:[(0,a.jsxs)("p",{children:[e.bankName," - ",e.accountNumber]}),(0,a.jsx)("p",{children:e.createdAt?(0,tJ.GP)(new Date(e.createdAt),"yyyy年MM月dd日 HH:mm",{locale:tq.G}):"日期未知"}),e.reviewNote&&(0,a.jsxs)("p",{className:"text-xs mt-1",children:["備註:",e.reviewNote]})]})]})},e.id)),y&&(0,a.jsx)(h.$,{variant:"outline",className:"w-full mt-4",onClick:b,disabled:v,children:v?(0,a.jsx)(a.Fragment,{children:(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin"})}):"載入更多"})]})]})]})]})}var sT=s(14188),s$=s(2962),sP=s(6524);let sD=I.Ik({bodyMarkdown:I.Yj().optional(),sections:I.g1(I.Yj(),I.bz()).optional(),advisorDisplayName:I.Yj().optional(),updatedAt:I.Yj().optional()}),sF=[{key:"summary",label:"第三章 \xb7 理財規劃書摘要",placeholder:"重點摘要:理財需求、財務現況、目標、分析與規劃方向…"},{key:"familyStatus",label:"第四章 \xb7 家庭狀況",placeholder:"婚姻狀況、扶養人數、子女年齡、家庭責任等;未填寫時系統會依受益人資料自動摘要…"},{key:"goals",label:"第四章 \xb7 理財目標設定(補充)",placeholder:"客戶背景、價值認知、風險偏好與目標之補充說明…"},{key:"currentStatus",label:"第五章 \xb7 財務現況分析",placeholder:"針對資產負債、現金流、保險與資產配置的分析…"},{key:"needsAnalysis",label:"第六章 \xb7 目標需求分析",placeholder:"現金流需求、緊急備用金、所需報酬率與缺口分析…"},{key:"benefit",label:"第八章 \xb7 效益分析",placeholder:"規劃執行後的預期效益與目標達成率…"},{key:"actionPlan",label:"第九章 \xb7 執行計畫",placeholder:"執行步驟與時間點(現金管控、儲蓄、保單調整、資產重分配…)"},{key:"reviewSchedule",label:"第十章 \xb7 定期檢視",placeholder:"檢視頻率與觸發調整的情況…"},{key:"responsibilities",label:"第二章 \xb7 責任與義務聲明(覆寫)",placeholder:"如需覆寫預設的責任義務聲明,於此填寫…"}],s_=[{key:"financial",label:"財務管理"},{key:"asset",label:"資產管理"},{key:"risk",label:"風險管理"},{key:"tax",label:"稅務規劃"},{key:"retirement",label:"退休規劃"},{key:"estate",label:"遺產/傳承規劃"}];function sV({open:e,onOpenChange:t,userId:s,userLabel:i}){let{toast:l}=(0,p.dj)(),{user:n}=(0,f.A)(),[c,d]=(0,r.useState)(!1),[o,m]=(0,r.useState)(!1),[x,j]=(0,r.useState)(""),[v,g]=(0,r.useState)({}),[y,b]=(0,r.useState)({}),[w,N]=(0,r.useState)(void 0),k=(0,r.useMemo)(()=>`/api/advisor/clients/${encodeURIComponent(s)}/financial-report-note`,[s]);(0,r.useEffect)(()=>{if(!e||!n)return;let t=!1;return(async()=>{d(!0);try{let e=await n.getIdToken(),s=await fetch(k,{method:"GET",headers:{Authorization:`Bearer ${e}`}});if(!s.ok)throw Error(`HTTP ${s.status}`);let a=await s.json(),r=sD.safeParse(a);if(!r.success)throw Error("回應格式錯誤");if(t)return;j(r.data.bodyMarkdown??"");let i=r.data.sections??{},l=i.recommendations??{},c={};for(let e of sF)"string"==typeof i[e.key]&&(c[e.key]=i[e.key]);let d={};for(let e of s_)"string"==typeof l[e.key]&&(d[e.key]=l[e.key]);g(c),b(d),N(r.data.updatedAt)}catch(t){let e=t instanceof Error?t:Error(String(t));K.Cp(e,{level:"error",extra:{message:"載入顧問報表建議失敗",endpoint:k},tags:{source:"ClientReportNoteDialog.load"}}),l({title:"載入失敗",description:"無法載入顧問建議,請稍後再試。",variant:"destructive"})}finally{t||d(!1)}})(),()=>{t=!0}},[e,n,k,l]);let C=async()=>
8{if(!n)return void l({title:"錯誤",description:"用戶未登入",variant:"destructive"});m(!0);try{let e=await n.getIdToken(),t=await fetch(k,{method:"PUT",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({bodyMarkdown:x,sections:{...v,recommendations:y}})});if(!t.ok)throw Error(`HTTP ${t.status}`);l({title:"已儲存",description:"理財規劃書顧問建議已更新。"}),N(new Date().toISOString())}catch(t){let e=t instanceof Error?t:Error(String(t));K.Cp(e,{level:"error",extra:{message:"儲存顧問報表建議失敗",endpoint:k},tags:{source:"ClientReportNoteDialog.save"}}),l({title:"儲存失敗",description:"無法儲存顧問建議,請稍後再試。",variant:"destructive"})}finally{m(!1)}},S=c||o;return(0,a.jsx)(A.lG,{open:e,onOpenChange:t,children:(0,a.jsxs)(A.Cf,{className:"max-w-3xl",children:[(0,a.jsxs)(A.c7,{children:[(0,a.jsx)(A.L3,{children:"理財規劃書建議"}),(0,a.jsxs)(A.rr,{children:["編輯客戶「",i,"」的理財規劃書內容。各章節留空時,系統會依財務資料自動產生預設內容;填寫後將覆寫該章節。支援 Markdown。"]})]}),(0,a.jsxs)("div",{className:"max-h-[62vh] space-y-4 overflow-y-auto pr-1",children:[(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)(u.J,{children:"整體建議摘要"}),(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:w?`最後更新:${w}`:"尚未建立建議"}),(0,a.jsx)(E.T,{value:x,onChange:e=>j(e.target.value),placeholder:"整體建議摘要(未填第三章摘要時,將以此作為摘要)",className:"min-h-[120px]",disabled:S})]}),(0,a.jsxs)(sP.nD,{type:"multiple",className:"w-full",children:[sF.map(e=>(0,a.jsxs)(sP.As,{value:e.key,children:[(0,a.jsxs)(sP.$m,{className:"text-left text-sm",children:[e.label,v[e.key]?.trim()?(0,a.jsx)("span",{className:"ml-2 text-xs text-accent",children:"已填寫"}):null]}),(0,a.jsx)(sP.ub,{children:(0,a.jsx)(E.T,{value:v[e.key]??"",onChange:t=>g(s=>({...s,[e.key]:t.target.value})),placeholder:e.placeholder,className:"min-h-[140px]",disabled:S})})]},e.key)),(0,a.jsxs)(sP.As,{value:"recommendations",children:[(0,a.jsxs)(sP.$m,{className:"text-left text-sm",children:["第七章 \xb7 規劃建議(六面向)",Object.values(y).some(e=>e?.trim())?(0,a.jsx)("span",{className:"ml-2 text-xs text-accent",children:"已填寫"}):null]}),(0,a.jsx)(sP.ub,{className:"space-y-3",children:s_.map(e=>(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)(u.J,{className:"text-xs",children:e.label}),(0,a.jsx)(E.T,{value:y[e.key]??"",onChange:t=>b(s=>({...s,[e.key]:t.target.value})),placeholder:`${e.label}的建議…`,className:"min-h-[100px]",disabled:S})]},e.key))})]})]})]}),(0,a.jsxs)(A.Es,{children:[(0,a.jsx)(h.$,{variant:"outline",onClick:()=>t(!1),disabled:o,children:"關閉"}),(0,a.jsx)(h.$,{onClick:C,disabled:S,children:o?"儲存中...":"儲存"})]})]})})}function sB(){let{toast:e}=(0,p.dj)(),t=(0,i.useRouter)(),{user:s,setViewingUser:l}=(0,f.A)(),{bookings:n,isLoading:c,error:u,status:m,setStatus:x,startDate:j,setStartDate:v,endDate:g,setEndDate:y,keyword:b,setKeyword:w,reload:N,cancelBooking:k}=sb(),{clients:C}=sx(),[S,I]=(0,r.useState)(!1),[R,T]=(0,r.useState)(null),[$,P]=(0,r.useState)(""),[D,F]=(0,r.useState)(!1),[_,V]=(0,r.useState)(null),[B,L]=(0,r.useState)(!1),[z,O]=(0,r.useState)(null),U=(0,r.useMemo)(()=>new Set(C.filter(e=>e.isActive&&e.userId).map(e=>e.userId)),[C]),M=(0,r.useMemo)(()=>{let e=e=>"paid"===e?(0,a.jsx)(e4.E,{variant:"default",children:"已付款"}):"authorized"===e?(0,a.jsx)(e4.E,{variant:"secondary",children:"已授權"}):"pending"===e?(0,a.jsx)(e4.E,{variant:"outline",children:"待授權"}):"draft"===e?(0,a.jsx)(e4.E,{variant:"outline",children:"草稿"}):"cancelled"===e?(0,a.jsx)(e4.E,{variant:"destructive",children:"已取消"}):(0,a.jsx)(e4.E,{variant:"outline",children:e});return e.displayName="StatusBadge",e},[]),W=async()=>{if(R&&!D)try{F(!0),await k(R,$.trim()),I(!1),T(null),P(""),e({title:"已取消預約"})}catch(t){e({title:"取消預約失敗",description:t instanceof Error?t.message:"取消失敗",variant:"destructive"})}finally{F(!1)}};return(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsx)(d.ZB,{children:"預約管理"})}),(0,a.jsxs)(d.Wu,{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"flex flex-col md:flex-row md:items-end gap-3 justify-between",children:[(0,a.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-2 w-full",children:[(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"狀態"}),(0,a.jsxs)(tZ.l6,{value:m,onValueChange:x,children:[(0,a.jsx)(tZ.bq,{children:(0,a.jsx)(tZ.yv,{})}),(0,a.jsxs)(tZ.gC,{children:[(0,a.jsx)(tZ.eb,{value:"all",children:"全部"}),(0,a.jsx)(tZ.eb,{value:"paid",children:"已付款"}),(0,a.jsx)(tZ.eb,{value:"cancelled",children:"已取消"})]})]})]}),(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"開始日期"}),(0,a.jsx)(o.p,{type:"date",value:j,onChange:e=>v(e.target.value)})]}),(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"結束日期"}),(0,a.jsx)(o.p,{type:"date",value:g,onChange:e=>y(e.target.value)})]}),(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"搜尋"}),(0,a.jsx)(o.p,{placeholder:"姓名 / Email / 主題 / ID",value:b,onChange:e=>w(e.target.value)})]})]}),(0,a.jsx)("div",{className:"flex items-center gap-2",children:(0,a.jsx)(h.$,{variant:"outline",onClick:N,disabled:c,
8children:c?(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin"}):"重新整理"})})]}),u?(0,a.jsx)("div",{className:"text-sm text-destructive",children:u}):null,(0,a.jsxs)(s$.XI,{children:[(0,a.jsx)(s$.A0,{children:(0,a.jsxs)(s$.Hj,{children:[(0,a.jsx)(s$.nd,{children:"時間"}),(0,a.jsx)(s$.nd,{children:"客戶"}),(0,a.jsx)(s$.nd,{children:"主題"}),(0,a.jsx)(s$.nd,{children:"來源"}),(0,a.jsx)(s$.nd,{children:"狀態"}),(0,a.jsx)(s$.nd,{className:"text-right",children:"金額"}),(0,a.jsx)(s$.nd,{className:"text-right",children:"操作"})]})}),(0,a.jsx)(s$.BF,{children:0===n.length?(0,a.jsx)(s$.Hj,{children:(0,a.jsx)(s$.nA,{colSpan:7,className:"text-center text-muted-foreground py-10",children:c?(0,a.jsx)(sr.default,{size:40}):"沒有預約資料"})}):n.map(r=>{let i="number"==typeof r.paymentAmount?r.paymentAmount:"number"==typeof r.advisorFee?r.advisorFee:0,n=r.bookingContext,c=n?.source==="retirement"?"退休試算結果":n?.source==="insurance"?"保險缺口分析":null;return(0,a.jsxs)(s$.Hj,{children:[(0,a.jsxs)(s$.nA,{className:"whitespace-nowrap",children:[(0,a.jsxs)("div",{className:"font-medium",children:[r.date||"—"," ",r.time||""]}),(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:r.method||""})]}),(0,a.jsxs)(s$.nA,{children:[(0,a.jsx)("div",{className:"font-medium",children:r.userDisplayName||r.userEmail||r.userId||"—"}),(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:r.userEmail||""})]}),(0,a.jsxs)(s$.nA,{className:"max-w-[240px]",children:[(0,a.jsx)("div",{className:"truncate",children:r.topic||"—"}),r.cancellationReason?(0,a.jsxs)("div",{className:"text-xs text-muted-foreground truncate",children:["取消原因:",r.cancellationReason]}):null]}),(0,a.jsx)(s$.nA,{children:c?(0,a.jsx)(eE.m_,{content:n?.summary??"—",children:(0,a.jsx)(e4.E,{variant:"secondary",className:"text-xs font-normal cursor-default",children:c})}):(0,a.jsx)("span",{className:"text-muted-foreground text-xs",children:"—"})}),(0,a.jsx)(s$.nA,{children:M(r.status)}),(0,a.jsx)(s$.nA,{className:"text-right whitespace-nowrap",children:(0,sc.C)(i,{showSymbol:!0})}),(0,a.jsx)(s$.nA,{className:"text-right",children:(0,a.jsxs)("div",{className:"flex items-center justify-end gap-1",children:[("authorized"===r.status||"paid"===r.status)&&r.userId?(0,a.jsxs)(a.Fragment,{children:[U.has(r.userId)?(0,a.jsx)(h.$,{size:"sm",variant:"outline",onClick:()=>{O({userId:r.userId,label:r.userDisplayName||r.userEmail||r.userId}),L(!0)},children:"報表建議"}):null,(0,a.jsxs)(h.$,{size:"sm",variant:"outline",disabled:null!==_,onClick:async()=>{V(r.id);try{let e=s?await s.getIdToken():null;e&&await fetch("/api/advisor/clients/ensure-from-booking",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({bookingId:r.id})})}catch{}l(r.userId,r.userEmail||r.userId),e({title:"已切換檢視模式",description:`正在檢視客戶:${r.userDisplayName||r.userEmail||r.userId}`}),t.push("/dashboard"),V(null)},className:"flex items-center gap-1",children:[(0,a.jsx)(sT.A,{className:"h-3 w-3"}),"檢視客戶"]})]}):null,(0,a.jsx)(h.$,{size:"sm",variant:"destructive",onClick:()=>{var e;(e=r.id)&&(T(e),P(""),I(!0))},disabled:"cancelled"===r.status,children:"取消"})]})})]},r.id)})})]}),z?(0,a.jsx)(sV,{open:B,onOpenChange:e=>{L(e),e||O(null)},userId:z.userId,userLabel:z.label}):null,(0,a.jsx)(A.lG,{open:S,onOpenChange:I,children:(0,a.jsxs)(A.Cf,{children:[(0,a.jsxs)(A.c7,{children:[(0,a.jsx)(A.L3,{children:"取消預約"}),(0,a.jsx)(A.rr,{children:"取消後將更新預約狀態;若已付款會標記需退款(實際退款流程後續串接)。"})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsx)("div",{className:"text-sm",children:"取消原因(選填)"}),(0,a.jsx)(E.T,{value:$,onChange:e=>P(e.target.value),placeholder:"例如:臨時行程衝突"})]}),(0,a.jsxs)(A.Es,{children:[(0,a.jsx)(h.$,{variant:"outline",onClick:()=>I(!1),disabled:D,children:"取消"}),(0,a.jsx)(h.$,{variant:"destructive",onClick:W,disabled:D,children:D?"處理中...":"確認取消"})]})]})})]})]})}function sL(){let{toast:e}=(0,p.dj)(),t=sE(),s=(0,r.useMemo)(()=>t.summary?[{title:"總收入",value:t.summary.totalRevenue},{title:"平台服務費(10%)",value:t.summary.totalPlatformFee},{title:"淨收入",value:t.summary.totalAdvisorRevenue}]:null,[t.summary]),i=async()=>{try{await t.exportCsv(),e({title:"已匯出 CSV"})}catch(t){e({title:"匯出失敗",description:t instanceof Error?t.message:"匯出失敗",variant:"destructive"})}};return(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsx)(d.ZB,{children:"收入管理"})}),(0,a.jsx)(d.Wu,{className:"space-y-4",children:(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsx)("div",{className:"flex flex-col md:flex-row md:items-end gap-3 justify-between",children:(0,a.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2 w-full",children:[(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"開始日期"}),(0,a.jsx)(o.p,{type:"date",value:t.startDate,onChange:e=>t.setStartDate(e.target.value)})]}),(0,a.jsxs)("div",{className:"space-y-1",children:[(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:"結束日期"}
8),(0,a.jsx)(o.p,{type:"date",value:t.endDate,onChange:e=>t.setEndDate(e.target.value)})]}),(0,a.jsxs)("div",{className:"flex items-end gap-2",children:[(0,a.jsx)(h.$,{variant:"outline",onClick:t.reload,disabled:t.isLoading,children:t.isLoading?(0,a.jsx)(eb.A,{className:"h-4 w-4 animate-spin"}):"重新整理"}),(0,a.jsx)(h.$,{onClick:i,disabled:t.isLoading,children:"匯出 CSV"})]})]})}),t.error?(0,a.jsx)("div",{className:"text-sm text-destructive",children:t.error}):null,s?(0,a.jsx)("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-3",children:s.map(e=>(0,a.jsxs)(d.Zp,{children:[(0,a.jsx)(d.aR,{children:(0,a.jsx)(d.ZB,{className:"text-base",children:e.title})}),(0,a.jsx)(d.Wu,{className:"text-xl font-semibold",children:(0,sc.C)(e.value,{showSymbol:!0})})]},e.title))}):(0,a.jsx)("div",{className:"text-sm text-muted-foreground",children:"尚未載入摘要"}),(0,a.jsx)("div",{className:"flex items-center justify-between",children:(0,a.jsxs)(e4.E,{variant:"secondary",children:["筆數:",t.summary?.transactionCount??0]})}),(0,a.jsxs)(s$.XI,{children:[(0,a.jsx)(s$.A0,{children:(0,a.jsxs)(s$.Hj,{children:[(0,a.jsx)(s$.nd,{children:"日期"}),(0,a.jsx)(s$.nd,{children:"客戶"}),(0,a.jsx)(s$.nd,{className:"text-right",children:"金額"}),(0,a.jsx)(s$.nd,{className:"text-right",children:"平台費"}),(0,a.jsx)(s$.nd,{className:"text-right",children:"淨收入"})]})}),(0,a.jsx)(s$.BF,{children:0===t.items.length?(0,a.jsx)(s$.Hj,{children:(0,a.jsx)(s$.nA,{colSpan:5,className:"text-center text-muted-foreground py-10",children:t.isLoading?(0,a.jsx)(sr.default,{size:40}):"沒有資料"})}):t.items.map(e=>(0,a.jsxs)(s$.Hj,{children:[(0,a.jsx)(s$.nA,{className:"whitespace-nowrap",children:(0,a.jsxs)("div",{className:"font-medium",children:[e.date||"—"," ",e.time||""]})}),(0,a.jsxs)(s$.nA,{children:[(0,a.jsx)("div",{className:"font-medium",children:e.userDisplayName||e.userEmail||e.userId||"—"}),(0,a.jsx)("div",{className:"text-xs text-muted-foreground",children:e.userEmail||""})]}),(0,a.jsx)(s$.nA,{className:"text-right whitespace-nowrap",children:(0,sc.C)(e.amount,{showSymbol:!0})}),(0,a.jsx)(s$.nA,{className:"text-right whitespace-nowrap",children:(0,sc.C)(e.platformFee,{showSymbol:!0})}),(0,a.jsx)(s$.nA,{className:"text-right whitespace-nowrap",children:(0,sc.C)(e.advisorRevenue,{showSymbol:!0})})]},e.bookingId))})]})]})})]})}var sz=s(93806),sO=s(775),sU=s(20814),sM=s(90508);function sW(){let{toast:e}=(0,p.dj)(),t=(0,i.useRouter)(),{advisor:s,loading:l,isAdvisor:n}=(0,sz.s)(),{isAdmin:c}=(0,eR.q)(),{user:o}=(0,f.A)(),[u,m]=(0,r.useState)(0),[h,x]=(0,r.useState)(!1),j=(0,r.useMemo)(()=>{if(s)return{name:s.name||"",company:s.company||"",officeAddress:s.officeAddress||"",specialties:s.specialties||[],serviceAreas:s.serviceAreas||[],certifications:s.certifications||[],fee:s.fee||0,yearsOfExperience:s.yearsOfExperience||0,weeklySchedule:s.weeklySchedule||{},specificDates:s.specificDates||{},avatar:s.avatar||"",website:s.website||"",socialMedia:s.socialMedia||[],userId:s.userId||o?.uid,rating:s.rating||0,reviews:s.reviews||0,email:s.email||o?.email||"",customerReviews:s.customerReviews||[],id:s.id,advanceBookingDays:s.advanceBookingDays,bookingWindowDays:s.bookingWindowDays,certificationsUpdatedAt:s.certificationsUpdatedAt}},[s,o]),v=(0,r.useMemo)(()=>{if(!s)return;let e=s.certificationsUpdatedAt,t="string"==typeof e?e:"function"==typeof e?.toDate?e.toDate().toISOString():void 0;if(!t||!(0,sU.iQ)(t))return;let a=(0,sU.AD)(t);return a?a.toLocaleDateString("zh-TW",{year:"numeric",month:"2-digit",day:"2-digit"}):void 0},[s]),g=(0,r.useCallback)(async a=>{try{x(!0);let r={name:a.name,company:a.company||"",officeAddress:a.officeAddress||"",specialties:a.specialties,serviceAreas:a.serviceAreas,certifications:a.certifications||[],fee:a.fee,yearsOfExperience:a.yearsOfExperience||0,weeklySchedule:a.weeklySchedule||{},specificDates:a.specificDates||{},avatar:a.avatar,website:a.website||"",socialMedia:a.socialMedia.length>0?a.socialMedia:[],advanceBookingDays:a.advanceBookingDays,bookingWindowDays:a.bookingWindowDays,updatedAt:new Date().toISOString()};
8if(s?.id){if(await sO.n.updateAdvisor(s.id,r,{fromSelf:!0}),o)try{let e=await o.getIdToken();await (0,ee.b2)(e)}catch{}e({title:"更新成功!",description:"顧問資料已成功更新。"}),m(e=>e+1),t.refresh()}else{if(!c&&!n)return void e({variant:"destructive",title:"錯誤",description:"無法找到顧問資料"});let s={...r,userId:o?.uid||null,email:o?.email||null,rating:0,reviews:0,customerReviews:[],createdAt:new Date().toISOString()};await sO.n.addAdvisor(s),e({title:"建立成功!",description:"顧問資料已成功建立。"}),m(e=>e+1),t.refresh()}}catch(a){let t=a instanceof Error?a:Error(String(a));throw K.Cp(t,{level:"error",extra:{message:"儲存顧問資料時發生錯誤",operation:"advisor_profile_save",advisorId:s?.id},tags:{source:"AdvisorProfileSettings.handleSave"}}),e({variant:"destructive",title:"操作失敗",description:a instanceof Error?a.message:"系統發生錯誤,請稍後再試。"}),a}finally{x(!1)}},[s,c,n,o,e,t]);return l?(0,a.jsx)(sr.default,{className:"py-12",size:64}):n||c?(0,a.jsx)("div",{className:"space-y-6",children:(0,a.jsxs)(d.Zp,{children:[(0,a.jsxs)(d.aR,{children:[(0,a.jsx)(d.ZB,{children:"顧問資料"}),(0,a.jsx)(d.BT,{children:"編輯您的顧問資料,這些資訊將顯示在顧問列表中供用戶查看。"})]}),(0,a.jsx)(d.Wu,{children:(0,a.jsx)(sM.A,{initialData:j,userId:s?.userId||o?.uid,onSave:g,isSaving:h,showCancelButton:!1,avatarInputId:"advisor-avatar",certificationsLockedUntil:v},u)})]})}):(0,a.jsx)(d.Zp,{children:(0,a.jsx)(d.Wu,{className:"p-8 text-center",children:(0,a.jsx)("p",{className:"text-muted-foreground",children:"您目前不是顧問,無法編輯顧問資料。"})})})}function sZ(){let[e,t]=(0,r.useState)("dashboard");return(0,a.jsx)(sl.A,{children:(0,a.jsxs)(l.tU,{value:e,onValueChange:t,className:"space-y-4",children:[(0,a.jsxs)(l.j7,{className:"mb-2",children:[(0,a.jsx)(l.Xi,{value:"dashboard",children:"主頁"}),(0,a.jsx)(l.Xi,{value:"advisor-profile",children:"顧問資料"}),(0,a.jsx)(l.Xi,{value:"bookings",children:"預約管理"}),(0,a.jsx)(l.Xi,{value:"revenue",children:"收入管理"})]}),(0,a.jsx)(l.av,{value:"dashboard",children:(0,a.jsx)(sR,{})}),(0,a.jsx)(l.av,{value:"advisor-profile",children:(0,a.jsx)(sW,{})}),(0,a.jsx)(l.av,{value:"bookings",children:(0,a.jsx)(sB,{})}),(0,a.jsx)(l.av,{value:"revenue",children:(0,a.jsx)(sL,{})})]})})}var sH=s(8180),sJ=s(35347);let sG=["profile","notifications","sound","sponsorship","security","sharing","bookings","edit-history","data-import","developer","advisor","beta"];function sY(){let{isAdvisor:e,isLoading:t}=(0,sJ.b)(),s=(0,i.useSearchParams)(),n=(0,i.useRouter)(),c=(0,i.usePathname)(),[d,o]=(0,r.useState)("profile");return(0,r.useEffect)(()=>{let e=s.get("tab");if("subscription"===e){let e=s.get("plan"),t=new URLSearchParams({tab:"sponsorship"});e&&t.set("plan",e),n.replace(`${c}?${t.toString()}`);return}if("referral"===e){let e=s.get("ref"),t=new URLSearchParams({tab:"profile"});e&&t.set("ref",e),n.replace(`${c}?${t.toString()}`);return}e&&sG.includes(e)&&o(e)},[s,n,c]),(0,r.useEffect)(()=>{!t&&("advisor"!==d||e||o("profile"))},[t,e,d]),(0,a.jsx)("div",{className:"space-y-6",children:(0,a.jsxs)(l.tU,{value:d,onValueChange:e=>{o(e??"profile")},className:"space-y-4",children:[(0,a.jsx)("div",{className:"w-full min-w-0",children:(0,a.jsxs)(l.j7,{className:"w-full max-w-full overflow-x-auto whitespace-nowrap",children:[(0,a.jsx)(l.Xi,{value:"profile",children:"個人資料"}),(0,a.jsx)(l.Xi,{value:"notifications",children:"通知"}),(0,a.jsx)(l.Xi,{value:"sound",children:"音效"}),(0,a.jsx)(l.Xi,{value:"sponsorship",children:"贊助"}),(0,a.jsx)(l.Xi,{value:"security",children:"安全"}),(0,a.jsx)(l.Xi,{value:"sharing",children:"分享"}),(0,a.jsx)(l.Xi,{value:"bookings",children:"預約"}),(0,a.jsx)(l.Xi,{value:"edit-history",children:"修改紀錄"}),(0,a.jsx)(l.Xi,{value:"data-import",children:"資料管理"}),!t&&e&&(0,a.jsx)(l.Xi,{value:"advisor",children:"顧問"}),(0,a.jsx)(l.Xi,{value:"developer",children:"開發者"}),(0,a.jsx)(l.Xi,{value:"beta",children:"Beta"})]})}),(0,a.jsxs)(l.av,{value:"profile",className:"space-y-6",children:[(0,a.jsx)(ei,{}),(0,a.jsx)(ev,{})]}),(0,a.jsx)(l.av,{value:"notifications",children:(0,a.jsx)(eO,{})}),(0,a.jsx)(l.av,{value:"sound",children:(0,a.jsx)(eQ,{})}),(0,a.jsx)(l.av,{value:"sponsorship",children:(0,a.jsx)(sH.yO,{})}),(0,a.jsx)(l.av,{value:"security",children:(0,a.jsx)(tu,{})}),(0,a.jsx)(l.av,{value:"sharing",children:(0,a.jsx)(si,{})}),(0,a.jsx)(l.av,{value:"bookings",children:(0,a.jsx)(ty,{})}),(0,a.jsx)(l.av,{value:"edit-history",children:(0,a.jsx)(t$,{})}),(0,a.jsx)(l.av,{value:"data-import",children:(0,a.jsx)(tL,{})}),!t&&e&&(0,a.jsx)(l.av,{value:"advisor",children:(0,a.jsx)(sZ,{})}),(0,a.jsxs)(l.av,{value:"developer",className:"space-y-6",children:[(0,a.jsx)(tk.A,{}),(0,a.jsx)(tN,{})]}),(0,a.jsx)(l.av,{value:"beta",children:(0,a.jsx)(sH.dE,{})})]})})}}}]);

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.