PageSourceSearch

https://xynergy.ai/_next/static/chunks/8706-de7408c81abab60e.js

js xynergy.ai collected 2026-10-05 16:01:46 UTC 22,574 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8706],{1397:(e,t,a)=>{a.d(t,{BA:()=>n,Y6:()=>l,yZ:()=>r});let r=["foundation","balance_sheet","protection","planning","legacy"],n={foundation:"基礎盤點",balance_sheet:"資產負債",protection:"保障與風險",planning:"長期規劃",legacy:"傳承"};function s(e,t){return(e??[]).some(e=>e.type===t)}let i=(e,t)=>({done:e,progress:+!!e,missingItems:e?[]:[t]}),l=[{id:"add_account",label:"建立收入與支出帳戶",stage:"foundation",weight:10,xp:20,href:"/dashboard/accounts",hint:"建立收入與支出帳戶各一個",check:e=>{let t=!!e.accounts?.some(e=>"income"===e.type),a=!!e.accounts?.some(e=>"expense"===e.type),r=[];return t||r.push("收入帳戶"),a||r.push("支出帳戶"),{done:t&&a,progress:(Number(t)+Number(a))/2,missingItems:r}}},{id:"add_income",label:"新增一筆收入",stage:"foundation",weight:8,xp:15,href:"/dashboard/income",hint:"記錄第一筆收入",check:e=>i(s(e.ledgerEntries,"income"),"第一筆收入記錄")},{id:"add_expense",label:"新增一筆支出",stage:"foundation",weight:8,xp:15,href:"/dashboard/expense",hint:"記錄第一筆支出",check:e=>i(s(e.ledgerEntries,"expense"),"第一筆支出記錄")},{id:"add_birthday",label:"填寫生日",stage:"foundation",weight:4,xp:30,href:"/dashboard/settings?tab=profile",hint:"完善個人資料以取得更準確的試算",check:e=>i(!!(e.userProfile?.birthday||e.userProfile?.profile?.birthDate),"生日")},{id:"add_asset",label:"新增一項資產",stage:"balance_sheet",weight:10,xp:20,href:"/dashboard/assets",hint:"盤點你的資產",check:e=>i((e.assets?.length??0)>0,"資產記錄")},{id:"add_liability",label:"新增一項負債",stage:"balance_sheet",weight:6,xp:20,href:"/dashboard/liabilities",hint:"記錄貸款或其他負債",check:e=>i((e.liabilities?.length??0)>
10,"負債記錄")},{id:"add_insurance",label:"新增保險記錄",stage:"protection",weight:12,xp:25,href:"/dashboard/insurance",hint:"登錄保單以檢視保障狀態",check:e=>i((e.insurancePolicies?.length??0)>0,"保單記錄")},{id:"emergency_fund",label:"建立緊急預備金",stage:"protection",weight:8,xp:25,href:"/dashboard/assets",hint:"於資產新增現金或緊急預備金項目",check:e=>{let t=!!e.assets?.some(e=>e?.type==="emergency_fund"||e?.type==="cash"),a=(e.summary?.emergencyFundCoverageMonths??0)>0;return i(t||a,"緊急預備金")}},{id:"add_investment",label:"新增投資記錄",stage:"planning",weight:8,xp:20,href:"/dashboard/investments",hint:"建立你的投資組合",check:e=>i((e.investments?.length??0)>0,"投資記錄")},{id:"use_retirement",label:"規劃退休",stage:"planning",weight:8,xp:30,href:"/dashboard/retirement",hint:"執行蒙地卡羅分析試算",check:e=>i(!!e.dataTaskFlags?.use_retirement,"蒙地卡羅分析試算")},{id:"set_goal",label:"建立一個財務目標",stage:"planning",weight:6,xp:40,href:"/dashboard",hint:"設定第一個財務目標",check:e=>i((e.goals?.length??0)>0,"財務目標")},{id:"add_estate",label:"規劃傳承",stage:"legacy",weight:6,xp:25,href:"/dashboard/estate",hint:"建立遺囑、預立醫療決定或意定監護",check:e=>i(!!(e.hasWill||e.hasAdvanceDirective||e.hasGuardianship),"遺囑、預立醫療決定書或意定監護")},{id:"add_trust",label:"新增信託",stage:"legacy",weight:4,xp:25,href:"/dashboard/trust",hint:"規劃信託安排",check:e=>i((e.trusts?.length??0)>0,"信託規劃")},{id:"review_tax",label:"檢視稅務",stage:"planning",weight:0,xp:20,href:"/dashboard/tax",hint:"上傳稅務文件",featureReady:!1,check:e=>i((e.taxDocuments?.length??0)>0,"稅務文件")}];l.filter(e=>!1!==e.featureReady).map(e=>e.id)},4690:(e,t,a)=>{a.d(t,{U:()=>C});var r=a(31615),n=a(73521),s=a(41178),i=a(19548),l=a(24571),o=a(76458),c=a(24720);function d(e,t){if(!o.db)throw Error("Firestore 尚未初始化");return(0,l.doc)(o.db,o.USERS,e,"checkins",t)}async function u(e,t){let a=await (0,l.getDoc)(d(e,t));if(!a.exists())return{days:[],makeups:[]};let r=a.data();return{days:Array.isArray(r?.days)?r.days.filter(e=>"number"==typeof e):[],makeups:Array.isArray(r?.makeups)?r.makeups.filter(e=>"number"==typeof e):[]}}function h(e,t){return new Set(t.map(t=>`${e}-${`${t}`.padStart(2,"0")}`))}async function g(e){if(!o.db||!e)return{aggregates:{...c.Zf},recentDates:new Set,makeupDates:new Set};let t=(0,c.eS)(),a=(0,c.go)(t),r=(0,c.go)((0,c.LM)(t,-35)),[n,s,i]=await Promise.all([(0,l.getDoc)((0,l.doc)(o.db,o.USERS,e)),u(e,a),u(e,r)]),d=(0,c.vg)(n.data()?.gamification?.checkin);return{aggregates:d,recentDates:new Set([...h(a,s.days),...h(r,i.days)]),makeupDates:new Set([...h(a,s.makeups),...h(r,i.makeups)])}}async function m(e,t,a){let r=new Set(a),n=new Set([(0,c.go)(t),(0,c.go)((0,c.LM)(t,-35))]),s=0,i=t;for(let t=0;t<744;t++){let t=(0,c.go)(i);if(!n.has(t)){if(n.size>=24)break;n.add(t);let{days:a}=await u(e,t);h(t,a).forEach(e=>r.add(e))}if(!r.has(i))break;s+=1,i=(0,c.LM)(i,-1)}return s}async function f(e,t){if(!o.db)throw Error("Firestore 尚未初始化");await (0,l.mZ)((0,l.doc)(o.db,o.USERS,e),{"gamification.checkin":t,updatedAt:(0,l.serverTimestamp)()})}async function p(e,t,a){let r={days:(0,l.hq)((0,c.kb)(t)),updatedAt:(0,l.serverTimestamp)()};a&&(r.makeups=(0,l.hq)((0,c.kb)(t))),await (0,l.setDoc)(d(e,(0,c.go)(t)),r,{merge:!0})}async function k(e,t){let a=(0,c.eS)();if(t.recentDates.has(a))throw Error("今日已簽到");await p(e,a,!1);let r=new Set(t.recentDates);r.add(a);let n=await m(e,a,r),s={...t.aggregates,totalDays:t.aggregates.totalDays+1,currentStreak:n,longestStreak:Math.max(t.aggregates.longestStreak,n),lastCheckIn:a};return await f(e,s),{aggregates:s,recentDates:r,makeupDates:t.makeupDates}}async function b(e,t,a,r){let n=(0,c.eS)();if(!(0,c.vh)(t,n))throw Error("只能補最近 7 天內的缺簽");if(a.recentDates.has(t))throw Error("該日已簽到,無需補簽");let s=(0,c.u9)(a.aggregates.makeupCount);if(!(0,c.S)(r,s))throw Error(`補簽需消耗 ${s} XP,目前不足`);await p(e,t,!0);let i=new Set(a.recentDates);i.add(t);let l=new Set(a.makeupDates);l.add(t);let o=a.aggregates.lastCheckIn&&a.aggregates.lastCheckIn>t?a.aggregates.lastCheckIn:t,d=i.has(n)?await m(e,n,i):(0,c.S9)(i,o),u={...a.aggregates,totalDays:a.aggregates.totalDays+1,currentStreak:d,longestStreak:Math.max(a.aggregates.longestStreak,d),makeupCount:a.aggregates.makeupCount+1,makeupXpSpent:a.aggregates.makeupXpSpent+s};return await f(e,u),{aggregates:u,recentDates:i,makeupDates:l}}var y=a(17256),x=a(58462);let w=["日","一","二","三","四","五","六"],v=0,S=new Set;function _(e){return S.add(e),()=>{S.delete(e)}}
1function D(){v+=1,S.forEach(e=>e())}function C(e){let t=e?.enabled!==!1,{user:a,viewingUserId:l}=(0,n.A)(),{toast:o}=(0,s.dj)(),{totalXp:d}=(0,x.I)(),u=t&&!l?a?.uid:void 0,h=(0,r.useSyncExternalStore)(_,()=>v,()=>0),[m,f]=(0,r.useState)({aggregates:{...c.Zf},recentDates:new Set,makeupDates:new Set}),[p,S]=(0,r.useState)(!0),[C,E]=(0,r.useState)(!1);(0,r.useEffect)(()=>{if(!u)return void S(!1);let e=!1;return S(!0),g(u).then(t=>{e||f(t)}).catch(e=>{let t=e instanceof Error?e:Error(String(e));i.Cp(t,{level:"error",extra:{message:"[useDailyCheckin] 載入簽到狀態失敗",uid:u},tags:{source:"useDailyCheckin.load"}})}).finally(()=>{e||S(!1)}),()=>{e=!0}},[u,h]);let j=(0,c.eS)(),$=m.recentDates.has(j),M=Math.max(0,d),N=(0,c.u9)(m.aggregates.makeupCount),A=(0,c.S)(M,N),I=(0,c.i2)(j).map(e=>{let t=m.recentDates.has(e),[a,r,n]=e.split("-").map(Number);return{ymd:e,weekdayLabel:w[new Date(a,r-1,n).getDay()],dayOfMonth:n,isToday:e===j,checked:t,isMakeup:m.makeupDates.has(e),canMakeup:!t&&(0,c.vh)(e,j)&&A}}),P=(0,r.useCallback)(async e=>{if(!u||C)return{ok:!1,streak:m.aggregates.currentStreak};if(m.recentDates.has((0,c.eS)()))return{ok:!0,streak:m.aggregates.currentStreak};E(!0);try{let t=await k(u,m);return f(t),(0,y.E)(u),D(),e?.silent||o({title:`✅ 簽到成功 +${c.dp} XP`,description:`已連續簽到 ${t.aggregates.currentStreak} 天`,duration:4e3}),{ok:!0,streak:t.aggregates.currentStreak}}catch(a){let t=a instanceof Error?a:Error(String(a));if("今日已簽到"===t.message)return D(),{ok:!0,streak:m.aggregates.currentStreak};return i.Cp(t,{level:"error",extra:{message:"[useDailyCheckin] 簽到失敗",uid:u},tags:{source:"useDailyCheckin.checkIn"}}),e?.silent||o({title:"簽到失敗",description:t.message,variant:"destructive"}),{ok:!1,streak:m.aggregates.currentStreak}}finally{E(!1)}},[u,C,m,o]),R=(0,r.useCallback)(async e=>{if(!u||C)return;let t=(0,c.u9)(m.aggregates.makeupCount);E(!0);try{let a=await b(u,e,m,M);f(a),(0,y.E)(u),D(),o({title:"❄️ 凍結補簽成功",description:`${e} 已補簽,消耗 ${t} XP(仍 +${c.dp} XP)`,duration:4e3})}catch(a){let t=a instanceof Error?a:Error(String(a));i.Cp(t,{level:"error",extra:{message:"[useDailyCheckin] 補簽失敗",uid:u,ymd:e},tags:{source:"useDailyCheckin.makeup"}}),o({title:"補簽失敗",description:t.message,variant:"destructive"})}finally{E(!1)}},[u,C,m,M,o]);return{enabled:!!u,loading:p,busy:C,todayChecked:$,currentStreak:m.aggregates.currentStreak,totalDays:m.aggregates.totalDays,makeupXpCost:N,availableXp:M,canAffordMakeup:A,weekCells:I,checkIn:P,makeup:R}}},17256:(e,t,a)=>{a.d(t,{E:()=>f,clearUserGamificationCached:()=>u,q:()=>p});var r=a(31615),n=a(41178),s=a(19548),i=a(76458),l=a(24571);let o=new Map,c="user_gamification_";function d(e){return`${c}${e}`}function u(e){if(e){o.delete(e);try{sessionStorage.removeItem(d(e))}catch{}return}o.clear();try{let e=[];for(let t=0;t<sessionStorage.length;t++){let a=sessionStorage.key(t);a?.startsWith(c)&&e.push(a)}e.forEach(e=>sessionStorage.removeItem(e))}catch{}}let h=0,g=new Set;function m(e){return g.add(e),()=>{g.delete(e)}}function f(e){u(e),h+=1,g.forEach(e=>e())}let p=e=>{let{toast:t}=(0,n.dj)(),a=(0,r.useSyncExternalStore)(m,()=>h,()=>0),c=e?function(e){let t=o.get(e);if(t)return t;let a=function(e){try{let t=sessionStorage.getItem(d(e));if(!t)return;let a=JSON.parse(t);if(!a||"object"!=typeof a)return;return a}catch{return}}(e);if(a)return o.set(e,a),a}(e):void 0,[u,g]=(0,r.useState)(()=>c??{referralCode:"",userProfile:null}),[f,p]=(0,r.useState)(!1);return(0,r.useEffect)(()=>{(async()=>{if(e&&i.db)try{let t=await (0,l.getDoc)((0,l.doc)(i.db,"users",e));if(t.exists()){let a=t.data(),r={referralCode:a.referralCode||"",userProfile:a};g(r);o.set(e,r);try{sessionStorage.setItem(d(e),JSON.stringify(r))}catch{}}}catch(a){let t=a instanceof Error?a:Error(String(a));s.Cp(t,{level:"error",extra:{message:"[useUserGamification] 載入用戶資料失敗",userId:e},tags:{source:"useUserGamification.loadUserData"}})}})()},[e,a]),{...u,copied:f,handleCopyReferralCode:()=>{navigator.clipboard.writeText(u.referralCode),p(!0),t({title:"已複製推薦碼",description:"推薦碼已複製到剪貼簿。"}),setTimeout(()=>p(!1),2e3)}}}},24720:(e,t,a)=>{a.d(t,{LM:()=>c,S:()=>m,S9:()=>f,Z1:()=>b,Zf:()=>n,dp:()=>r,e1:()=>p,eS:()=>o,go:()=>d,i2:()=>h,kb:()=>u,lj:()=>k,u9:()=>s,vg:()=>i,vh:()=>g});let r=5,n={totalDays:0,currentStreak:0,longestStreak:0,lastCheckIn:null,makeupCount:0,makeupXpSpent:0};function s(e){if(e<=0)return 10;
1if(1===e)return 20;let t=10,a=20;for(let r=2;r<=e;r++){let e=t+a;t=a,a=e}return a}function i(e){let t;if(!e||"object"!=typeof e)return{...n};let a=e=>"number"==typeof e&&Number.isFinite(e)&&e>=0?e:0,r=a(e.makeupXpSpent),i=a(e.makeupCount);if(0===i&&a(e.makeupUsed)>0&&(i=a(e.makeupUsed),0===r)){let e=0;for(let t=0;t<i;t++)e+=s(t);r=e}return 0===i&&r>0&&(i=function(e){if(e<=0)return 0;let t=0,a=e;for(;t<1e3;){let e=s(t);if(a<e)break;a-=e,t+=1}return t}(r)),{totalDays:a(e.totalDays),currentStreak:a(e.currentStreak),longestStreak:a(e.longestStreak),lastCheckIn:"string"==typeof(t=e.lastCheckIn)&&t?t:null,makeupCount:i,makeupXpSpent:r}}function l(e){let t=e.getFullYear(),a=`${e.getMonth()+1}`.padStart(2,"0"),r=`${e.getDate()}`.padStart(2,"0");return`${t}-${a}-${r}`}function o(){return l(new Date)}function c(e,t){let[a,r,n]=e.split("-").map(Number),s=new Date(a,r-1,n);return s.setDate(s.getDate()+t),l(s)}function d(e){return e.slice(0,7)}function u(e){return Number(e.slice(8,10))}function h(e=o()){let t=[];for(let a=6;a>=0;a--)t.push(c(e,-a));return t}function g(e,t=o()){return e<t&&e>=c(t,-7)}function m(e,t){return e>=t}function f(e,t){let a=0,r=t;for(;e.has(r);)a+=1,r=c(r,-1);return a}function p(e){return e.totalDays*r}function k(e){return e.makeupXpSpent}function b(e){return e<=0?"今天開始簽到,衝一波!":1===e?"第一天簽到成功,明天繼續衝!":e<7?`再 ${7-e} 天就滿一週,加油加油!`:7===e?"連續一週了!你超猛的!":e<30?`連續 ${e} 天!繼續保持火焰!`:30===e?"滿月連簽達成!傳說開始了!":e<90?`${e} 天連簽中,穩穩的!`:`${e} 天!你就是堅持之王!`}},58462:(e,t,a)=>{a.d(t,{I:()=>u});var r=a(31615),n=a(73521),s=a(90481),i=a(17256),l=a(1397);function o(e){let t=l.Y6.filter(e=>!1!==e.featureReady).map(t=>{let a,r=t.check(e);return{id:t.id,label:t.label,stage:t.stage,weight:t.weight,href:t.href,hint:t.hint,done:r.done,progress:Math.min(1,Math.max(0,Number.isFinite(a=r.progress)?a:0)),missingItems:r.missingItems}}),a=t.reduce((e,t)=>e+t.weight,0),r=a>0?Math.round(t.reduce((e,t)=>e+t.weight*t.progress,0)/a*100):0,n={};for(let e of l.yZ){let a=t.filter(t=>t.stage===e),r=a.reduce((e,t)=>e+t.weight,0);n[e]=r>0?Math.round(a.reduce((e,t)=>e+t.weight*t.progress,0)/r*100):100}let s=t.filter(e=>!e.done);return{overall:r,byStage:n,sections:t,nextBestSection:s.length?s.reduce((e,t)=>{let a=l.yZ.indexOf(t.stage)-l.yZ.indexOf(e.stage);return a<0||0===a&&t.weight>e.weight?t:e}):void 0}}function c(e,t){return e.reduce((e,a)=>t(a)?e+(a.xp||0):e,0)}var d=a(24720);function u(){let{user:e}=(0,n.A)(),{rawData:t,financialSummary:a,isSummaryResolved:u}=(0,s.P)(),h=(0,i.q)(e?.uid);return{...(0,r.useMemo)(()=>{let e=(0,d.vg)(h.userProfile?.gamification?.checkin),{accounts:r=[],transactions:n=[],monthlyBalances:s=[],ledgerEntries:i=[],assets:g=[],liabilities:m=[],goals:f=[],investments:p=[],insurancePolicies:k=[],trusts:b=[],taxDocuments:y=[],dataTaskFlags:x={},hasWill:w=!1,hasAdvanceDirective:v=!1,hasGuardianship:S=!1}=t||{},_={userProfile:h.userProfile,accounts:r,transactions:n,monthlyBalances:s,ledgerEntries:i,goals:f,netWorth:a?.netWorth??0,assets:g,liabilities:m,investments:p,insurancePolicies:k,trusts:b,taxDocuments:y,dataTaskFlags:x,hasWill:w,hasAdvanceDirective:v,hasGuardianship:S,summary:{netWorth:a?.netWorth,savingsRate:a?.savingsRate,debtRatio:a?.debtRatio,emergencyFundCoverageMonths:a?.emergencyFundCoverageMonths,netWorthGrowthRate:a?.netWorthGrowthRate,monthlyIncome:a?.monthlyIncome,monthlyExpenses:a?.monthlyExpenses},checkin:e},D=l.Y6.filter(e=>!1!==e.featureReady).map(e=>({id:e.id,label:e.label,done:e.check(_).done,xp:e.xp,kind:"data",href:e.href,hint:e.hint})),C=function(e){let t=!!e.ledgerEntries?.some(e=>"income"===e.type)||!!e.transactions?.some(e=>"income"===e.type),a=!!e.ledgerEntries?.some(e=>"expense"===e.type)||!!e.transactions?.some(e=>"expense"===e.type),r=(e.goals?.length||0)>0,n=e.netWorth??0,s=(e.assets?.length||0)>0,i=(e.liabilities?.length||0)>0,l=(e.investments?.length||0)>0,c=(e.insurancePolicies?.length||0)>0,{overall:d,byStage:u}=o(e),h=e.summary,g=h?.monthlyIncome??0,m=h?.monthlyExpenses??0,f=i&&h?.debtRatio!=null&&h.debtRatio<50,p=h?.emergencyFundCoverageMonths??0,k=!!e.dataTask
1Flags?.use_retirement,b=!!(e.hasWill||e.hasAdvanceDirective||e.hasGuardianship),y=e.checkin?.longestStreak??0,x=e.goals?.some(e=>"retirement"===e.category||e.name?.includes("退休"))||!1;return[{id:"first_income",name:"初次入帳",label:"記錄第一筆收入",achieved:t,xp:20},{id:"first_expense",name:"開始記帳",label:"記錄第一筆支出",achieved:a,xp:20},{id:"first_goal",name:"立定目標",label:"建立第一個財務目標",achieved:r,xp:30},{id:"first_asset",name:"資產起步",label:"新增第一項資產",achieved:s,xp:20},{id:"first_liability",name:"誠實面對",label:"記錄第一項負債",achieved:i,xp:20},{id:"first_investment",name:"投資新手",label:"記錄第一筆投資",achieved:l,xp:25},{id:"first_insurance",name:"風險意識",label:"新增第一份保險",achieved:c,xp:25},{id:"foundation_complete",name:"打好地基",label:"完成「基礎盤點」階段",achieved:100===u.foundation,xp:60},{id:"data_100",name:"全景視野",label:"資料完整度達 100%",achieved:100===d,xp:150},{id:"emergency_fund_3m",name:"安全氣囊",label:"緊急預備金可支撐 3 個月支出",achieved:p>=3,xp:80},{id:"positive_cashflow",name:"收支健康",label:"本月收入大於支出",achieved:m>0&&g>m,xp:60},{id:"low_debt",name:"輕裝上陣",label:"負債比低於 50%",achieved:f,xp:50},{id:"retirement_done",name:"未雨綢繆",label:"完成退休蒙地卡羅試算",achieved:k,xp:50},{id:"legacy_done",name:"傳承有序",label:"完成至少一項傳承規劃",achieved:b,xp:50},{id:"complete_financial_plan",name:"全方位規劃",label:"設定退休、保險、投資",achieved:x&&c&&l,xp:200},{id:"streak_7",name:"堅持一週",label:"連續簽到 7 天",achieved:y>=7,xp:30},{id:"streak_30",name:"月月報到",label:"連續簽到 30 天",achieved:y>=30,xp:100},{id:"streak_90",name:"一季不斷",label:"連續簽到 90 天",achieved:y>=90,xp:200},{id:"streak_180",name:"半年如一",label:"連續簽到 180 天",achieved:y>=180,xp:300},{id:"streak_365",name:"全年無休",label:"連續簽到 365 天",achieved:y>=365,xp:500},{id:"networth_100k",name:"小有積蓄",label:"淨值達 100,000",achieved:n>=1e5,xp:50},{id:"networth_500k",name:"穩健累積",label:"淨值達 500,000",achieved:n>=5e5,xp:75},{id:"networth_1m",name:"百萬俱樂部",label:"淨值達 1,000,000",achieved:n>=1e6,xp:100},{id:"networth_5m",name:"財富自由前哨",label:"淨值達 5,000,000",achieved:n>=5e6,xp:200}]}(_),E=function(e){let{byStage:t}=o(e),a=e.summary?.netWorthGrowthRate??0,r=e.summary?.savingsRate??0;return[{id:"stage_foundation",label:`完成「${l.BA.foundation}」階段`,reached:100===t.foundation,xp:50},{id:"stage_balance_sheet",label:`完成「${l.BA.balance_sheet}」階段`,reached:100===t.balance_sheet,xp:60},{id:"stage_protection",label:`完成「${l.BA.protection}」階段`,reached:100===t.protection,xp:80},{id:"stage_planning",label:`完成「${l.BA.planning}」階段`,reached:100===t.planning,xp:100},{id:"stage_legacy",label:`完成「${l.BA.legacy}」階段`,reached:100===t.legacy,xp:120},{id:"networth_growth_positive",label:"淨值較上月成長",reached:a>0,xp:80},{id:"savings_rate_20",label:"儲蓄率達 20%",reached:r>=20,xp:80}]}(_),j=o(_),$=Math.max(0,c(D,e=>e.done)+c(C,e=>e.achieved)+c(E,e=>e.reached)+(0,d.e1)(e)-(0,d.lj)(e)),{level:M,percent:N,nextLevelXp:A,current:I}=function(e){if(!Number.isFinite(e)||e<0)return{level:1,percent:0,nextLevelXp:100,current:0};let t=Math.floor(e/100)+1,a=e%100;return{level:t,percent:Math.min(100,Math.round(a/100*100)),nextLevelXp:100,current:a}}($);return{tasks:D,dataTasks:D.filter(e=>"data"===e.kind),achievements:C,milestones:E,completedTasks:D.filter(e=>e.done),incompleteTasks:D.filter(e=>!e.done),completedAchievements:C.filter(e=>e.achieved),incompleteAchievements:C.filter(e=>!e.achieved),completedMilestones:E.filter(e=>e.reached),incompleteMilestones:E.filter(e=>!e.reached),totalXp:$,level:M,percent:N,nextLevelXp:A,current:I,completeness:j,promptsReady:u}},[t,a,h.userProfile,u]),userGamification:h}}},78706:(e,t,a)=>{a.d(t,{S:()=>g,o:()=>h});var r=a(85047),n=a(82520),s=a(21410),i=a(68341),l=a(60661),o=a(33022),c=a(4690),d=a(24720),u=a(34961);function h({weekCells:e,todayChecked:t,busy:a,makeupXpCost:n,canAffordMakeup:o,onCheckIn:c,onMakeup:g,compact:m=!1}){let f=m?"h-10 w-10":"h-9 w-9";return(0,r.jsx)("div",{className:"flex items-end justify-center gap-2",children:e.map(e=>(0,r.jsxs)("div",{className:"flex flex-col items-center gap-1.5",children:[(0,r.jsx)("span",{className:(0,u.cn)("text-[11px] font-semibold",e.isToday?"text-accent":"text-muted-foreground"),children:e.weekdayLabel}),e.isToday?t?(0,r.jsx)("span",{className:(0,u.cn)("flex items-center justify-center rounded-full bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm",f),title:"今日已簽到",children:(0,r.jsx)(i.A,{className:"h-5 w-5",strokeWidth:3})}):c?(0,r.jsx)(s.$,{size:"sm",className:(0,u.cn)("rounded-full px-0 text-xs",f),disabled:a,onClick:c,title:`簽到 +${d.dp} XP`,children:"簽"}):(0,r.jsx)("span",{className:(0,u.cn)("rounded-full bg-muted",f),title:"今日尚未簽到"}):e.checked&&e.isMakeup?(0,r.jsx)("span",{className:(0,u.cn)("flex items-center justify-center rounded-full bg-sky-100 text-sky-600 ring-2 ring-sky-300/80 dark:bg-sky-900/50 dark:text-sky-300",f),title:`${e.ymd} 凍結補簽`,children:(0,r.jsx)(l.A,{className:"h-4 w-4"})}):e.checked?(0,r.jsx)("span",{className:(0,u.cn)("flex items-center justify-center rounded-full bg-gradient-to-br from-amber-400 to-orange-500 text-white shadow-sm",f),title:`${e.ymd} 已簽到`,children:(0,r.jsx)(i.A,{className:"h-4 w-4",strokeWidth:3})}):e.canMakeup&&g?(0,r.jsx)("button",{type:"button",disabled:a,onClick:()=>g(e.ymd),className:(0,u.cn)("rounded-full bg-muted/80 transition-colors hover:bg-muted hover:ring-2 hover:ring-sky-400/60 disabled:opacity-50",f),title:`凍結補簽 ${e.ymd}(消耗 ${n} XP)`,"aria-label":`凍結補簽 ${e.ymd}`}):(0,r.jsx)("span",{className:(0,u.cn)("flex items-center justify-center rounded-full bg-muted/80 text-muted-foreground",f),title:e.canMakeup?`${e.ymd} 可凍結補簽`:`${e.ymd} 未簽到${!o?`(需 ${n} XP)`:""}`})]},e.ymd))})}function g(){let{enabled:e,loading:t,busy:a,todayChecked:s,currentStreak:i,totalDays:l,makeupXpCost:u,canAffordMakeup:g,availableXp:m,weekCells:f,checkIn:p,makeup:k}=(0,c.U)();return!e||t?null:(0,r.jsx)(n.Zp,{children:(0,r.jsxs)(n.Wu,{className:"flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between",children:[(0,r.jsxs)("div",{className:"flex items-center gap-3",children:[(0,r.jsx)("div",{className:"flex h-12 w-12 items-center justify-center rounded-full bg-orange-100 dar
1k:bg-orange-900/40",children:(0,r.jsx)(o.A,{className:"h-6 w-6 text-orange-500"})}),(0,r.jsxs)("div",{children:[(0,r.jsxs)("p",{className:"text-sm font-semibold",children:["每日簽到",(0,r.jsxs)("span",{className:"ml-2 text-orange-500",children:["連續 ",i," 天"]})]}),(0,r.jsxs)("p",{className:"text-xs text-muted-foreground",children:["每日 +",d.dp," XP・累計 ",l," 天・下次凍結 ",u," XP (可用 ",m,")"]})]})]}),(0,r.jsx)(h,{weekCells:f,todayChecked:s,busy:a,makeupXpCost:u,canAffordMakeup:g,onCheckIn:()=>void p(),onMakeup:k})]})})}}}]);

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.