PageSourceSearch

https://xynergy.ai/_next/static/chunks/4498-a49690890888c84d.js

js xynergy.ai collected 2026-10-05 16:00:50 UTC 19,195 bytes, 20 lines download raw bytes

1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4498],{41717:(e,t,r)=>{r.d(t,{Ko:()=>d,V5:()=>a,cG:()=>i,hk:()=>n});let a={income:{name:"綜合所得稅申報",startDate:{month:5,day:1},endDate:{month:5,day:31},type:"income",description:"個人綜合所得稅申報期限"},house:{name:"房屋稅",startDate:{month:5,day:1},endDate:{month:5,day:31},type:"house",description:"房屋稅繳納期限"},land:{name:"地價稅",startDate:{month:11,day:1},endDate:{month:11,day:30},type:"land",description:"地價稅繳納期限"},vehicle:{name:"使用牌照稅",startDate:{month:4,day:1},endDate:{month:4,day:30},type:"vehicle",description:"使用牌照稅繳納期限"},fuel:{name:"燃料稅",startDate:{month:7,day:1},endDate:{month:7,day:31},type:"fuel",description:"燃料稅繳納期限"}};function i(e){let t=[];return Object.entries(a).forEach(([r,a])=>{let i=new Date(e,a.startDate.month-1,a.startDate.day),n=new Date(e,a.endDate.month-1,a.endDate.day);t.push({taxType:r,taxName:a.name,startDate:i.toISOString(),endDate:n.toISOString(),year:e,description:a.description})}),t}function n(){return new Date().getFullYear()}function d(){return Object.keys(a)}},58552:(e,t,r)=>{r.d(t,{e:()=>y});var a=r(31615),i=r(24571),n=r(76458),d=r(15418);let c=d.Ik({userId:d.Yj().min(1,"userId 不能為空"),taxType:d.k5(["income","house","land","vehicle","fuel","entertainment","stamp"],{message:"稅務類型必須是 income, house, land, vehicle, fuel, entertainment 或 stamp"}),taxName:d.Yj().min(1,"稅務名稱不能為空"),year:d.ai().int().min(2020,"年度必須大於等於 2020"),startDate:d.Yj().datetime("開始日期格式錯誤"),endDate:d.Yj().datetime("結束日期格式錯誤"),enabled:d.zM(),reminderDays:d.YO(d.ai().int().min(1).max(30)).refine(e=>0===e.length||e.every(e=>[1,3,7].includes(e)),"提醒天數必須是 1、3 或 7 天"),notifiedDays:d.YO(d.ai().int().min(1).max(30)).default([]),createdAt:d.Yj().datetime(),updatedAt:d.Yj().datetime()}),s=c.omit({createdAt:!0,updatedAt:!0,notifiedDays:!0}),o=c.partial().pick({enabled:!0,reminderDays:!0,notifiedDays:!0});var u=r(18654);let l=()=>{if(!n.db)throw Error("Firestore 尚未初始化");return n.db},f=e=>{if(!e||"object"!=typeof e)return e;let t={...e};if(t.createdAt&&(t.createdAt instanceof i.Timestamp||t.createdAt?.toDate)){let e=t.createdAt instanceof i.Timestamp?t.createdAt:i.Timestamp.fromMillis(1e3*t.createdAt.seconds+(t.createdAt.nanoseconds||0)/1e6);t.createdAt=e.toDate().toISOString()}else t.createdAt?.seconds&&(t.createdAt=new Date(1e3*t.createdAt.seconds).toISOString());if(t.updatedAt&&(t.updatedAt instanceof i.Timestamp||t.updatedAt?.toDate)){let e=t.updatedAt instanceof i.Timestamp?t.updatedAt:i.Timestamp.fromMillis(1e3*t.updatedAt.seconds+(t.updatedAt.nanoseconds||0)/1e6);t.updatedAt=e.toDate().toISOString()}else t.updatedAt?.seconds&&(t.updatedAt=new Date(1e3*t.updatedAt.seconds).toISOString());return t},m={async createTaxReminder(e){try{let t=s.parse(e),r=i.Timestamp.now(),a={...t,notifiedDays:[],createdAt:r,updatedAt:r};return(await (0,i.gS)((0,i.rJ)(l(),n.TAX_REMINDERS),a)).id}catch(e){throw(0,u.vV)("建立稅務提醒失敗:",e),e}},async getTaxReminders(e,t){try{let r=l(),a=(0,i.P)((0,i.rJ)(r,n.TAX_REMINDERS),(0,i._M)("userId","==",e),(0,i.My)("year","desc"),(0,i.My)("startDate","asc"));void 0!==t&&(a=(0,i.P)((0,i.rJ)(r,n.TAX_REMINDERS),(0,i._M)("userId","==",e),(0,i._M)("year","==",t),(0,i.My)("startDate","asc")));let d=await (0,i.GG)(a),s=[];return d.forEach(e=>{let t=f(e.data());try{let r=c.parse(t);s.push({...r,id:e.id})}catch(t){(0,u.vV)(`稅務提醒資料驗證失敗 (${e.id}):`,t)}}),s}catch(e){throw(0,u.vV)("取得稅務提醒失敗:",e),e}},async getTaxReminder(e){try{let t=(0,i.doc)(l(),n.TAX_REMINDERS,e),r=await (0,i.getDoc)(t);if(!r.exists())return null;let a=f(r.data());return{...c.parse(a),id:r.id}}catch(e){throw(0,u.vV)("取得稅務提醒失敗:",e),e}},async updateTaxReminder(e,t){try{let r={...o.parse(t),updatedAt:i.Timestamp.now()};await (0,i.mZ)((0,i.doc)(l(),n.TAX_REMINDERS,e),r)}catch(e){throw(0,u.vV)("更新稅務提醒失敗:",e),e}},async checkTaxReminderExists(e,t,r){try{let a=(0,i.P)((0,i.rJ)(l(),n.TAX_REMINDERS),(0,i._M)("userId","==",e),(0,i._M)("taxType","==",t),(0,i._M)("year","==",r));return!(await (0,i.GG)(a)).empty}catch(e){return(0,u.vV)("檢查稅務提醒是否存在失敗:",e),!1}}};var p=r(41717);function y({userId:e,autoLoad:t=!0,delayMs:r}={}){let[i,n]=(0,a.useState)([]),[d,c]=(0,a.useState)(!1),[s,o]=(0,a.useState)(null),l=(0,a.useRef)(!1),f=(0,a.useRef)(null),g=(0,a.useCallback)(async()=>
1{if(!e)return void n([]);c(!0),o(null);try{let t=(0,p.hk)(),r=await m.getTaxReminders(e,t);n(r),l.current=!0}catch(e){(0,u.vV)("載入稅務提醒失敗:",e),o(e)}finally{c(!1)}},[e]),h=(0,a.useRef)(g);(0,a.useEffect)(()=>{h.current=g},[g]);let A=(0,a.useCallback)(async t=>{if(!e)throw Error("用戶未登入");try{let e=await m.createTaxReminder(t);return await h.current(),e}catch(e){throw(0,u.vV)("建立稅務提醒失敗:",e),e}},[e]),D=(0,a.useCallback)(async(e,t)=>{try{let{id:r,userId:a,...i}=t;await m.updateTaxReminder(e,i),await h.current()}catch(e){throw(0,u.vV)("更新稅務提醒失敗:",e),e}},[]),w=(0,a.useCallback)((e,t)=>i.some(r=>r.taxType===e&&r.year===t),[i]),v=(0,a.useCallback)(()=>{let e=new Date,t=[];return i.forEach(r=>{if(!r.enabled)return;let a=new Date(r.endDate),i=Math.ceil((a.getTime()-e.getTime())/864e5);i<0||r.reminderDays.forEach(e=>{i!==e||r.notifiedDays.includes(e)||t.push({id:`tax-${r.id}-${e}`,title:`${r.taxName}提醒`,message:`${r.taxName}將在${e}天後到期(${a.toLocaleDateString("zh-TW",{year:"numeric",month:"2-digit",day:"2-digit"})})`,createdAt:new Date().toISOString(),read:!1,data:{type:"tax",taxReminderId:r.id,daysUntilDue:e,url:"/dashboard/tax?fn=calendar"}})})}),t},[i]);return(0,a.useEffect)(()=>{if(e&&t&&!l.current)return f.current&&clearTimeout(f.current),f.current=setTimeout(()=>{h.current()},void 0!==r?r:3e3+2e3*Math.random()),()=>{f.current&&clearTimeout(f.current)}},[e,t,r]),(0,a.useEffect)(()=>{e||(n([]),l.current=!1)},[e]),{reminders:i,loading:d,error:s,loadReminders:g,createReminder:A,updateReminder:D,getUpcomingNotifications:v,checkReminderExists:w}}},64498:(e,t,r)=>{r.d(t,{h:()=>b,S:()=>I});var a=r(85047),i=r(31615),n=r(73521),d=r(93806),c=r(24571),s=r(76458),o=r(18654);function u(e){let t=function(e){let t=e.updatedAt??e.createdAt;if(!t)return 0;let r="string"==typeof t?new Date(t):t.toDate?.()??new Date(String(t));return isNaN(r.getTime())?0:r.getTime()}(e);if(t<=0)return!1;let r=Date.now();return"paid"===e.status||"cancelled"===e.status?t>=r-9e5:t>=r-12e4}function l(e,t){let r=e.date?new Date(e.date).toLocaleDateString("zh-TW"):"",a=e.time||"";if("pending"===e.status&&"added"===t){let t;try{if(e.createdAt){let r=new Date(e.createdAt);t=isNaN(r.getTime())?new Date().toISOString():r.toISOString()}else t=new Date().toISOString()}catch{t=new Date().toISOString()}let i=new Date().toISOString(),n=new Date(new Date(t).getTime()+6e5).toISOString();return{id:`booking-${e.id}-pending`,title:"預約待完成授權",message:`您有一筆預約待完成授權
2顧問:${e.advisorName}
3日期:${r} ${a}
4請在 10 分鐘內完成授權及付款`,createdAt:i,expiresAt:n,data:{bookingId:e.id,type:"pending",url:`/advisor?bookingId=${e.id}`}}}if("authorized"===e.status&&"modified"===t){let t,i=new Date().toISOString();try{if(e.createdAt){let r=new Date(e.createdAt);isNaN(r.getTime())||(t=new Date(r.getTime()+6e5).toISOString())}}catch{}return{id:`booking-${e.id}-authorized`,title:"預約待完成付款",message:`您的預約已完成授權,請在 10 分鐘內完成付款
5顧問:${e.advisorName}
6日期:${r} ${a}
7請點擊完成付款`,createdAt:i,expiresAt:t,data:{bookingId:e.id,type:"authorized",url:`/advisor?bookingId=${e.id}`}}}if("paid"===e.status){let t=e.calendarLink?`
8
9點擊以下連結加入 Google 行事曆:
10${e.calendarLink}`:"";return{id:`booking-${e.id}-paid`,title:"預約付款完成",message:`預約已確認並完成付款
11顧問:${e.advisorName}
12日期:${r} ${a}${t}`,createdAt:e.updatedAt||new Date().toISOString(),data:{bookingId:e.id,type:"paid",url:e.calendarLink||`/payment/success?bookingId=${e.id}`}}}return"cancelled"===e.status?{id:`booking-${e.id}-cancelled`,title:"預約已取消",message:`您的預約已取消
13顧問:${e.advisorName}
14日期:${r} ${a}`,createdAt:e.updatedAt||new Date().toISOString(),data:{bookingId:e.id,type:"cancelled"}}:null}function f(e,t){let r=e.date?new Date(e.date).toLocaleDateString("zh-TW"):"",a=e.time||"";if("paid"===e.status){let t=e.calendarLink?`
15
16點擊以下連結加入 Google 行事曆:
17${e.calendarLink}`:"";return{id:`advisor-booking-${e.id}
17-paid`,title:"收到新預約",message:`用戶 ${e.userDisplayName||e.userEmail} 已完成付款
18日期:${r} ${a}
19主題:${e.topic}${t}`,createdAt:e.updatedAt||new Date().toISOString(),data:{bookingId:e.id,type:"paid",url:e.calendarLink||"/advisor"}}}return"cancelled"===e.status?{id:`advisor-booking-${e.id}-cancelled`,title:"預約已取消",message:`用戶 ${e.userDisplayName||e.userEmail} 已取消預約
20日期:${r} ${a}`,createdAt:e.updatedAt||new Date().toISOString(),data:{bookingId:e.id,type:"cancelled"}}:null}var m=r(58552),p=r(45762),y=r(28979),g=r(8958);let h="firestore:",A="app_notifications";function D(){let e=function(){try{let e=localStorage.getItem(g.RZ);if(e){let t=JSON.parse(e);return{enabled:t.enabled??g.wK.enabled,categories:{alerts:t.categories?.alerts??g.wK.categories.alerts,tasks:t.categories?.tasks??g.wK.categories.tasks},volume:t.volume??g.wK.volume}}}catch(e){}return g.wK}();y.jY.playSound("NOTIFICATION",e).catch(()=>{})}let w=()=>{},v={notifications:[],unreadCount:0,addNotification:w,markAsRead:w,markAllAsRead:w,removeNotification:w,clearExpiredNotifications:w},S=(0,i.createContext)(v);function b({children:e}){let{user:t}=(0,n.A)(),{advisor:r}=(0,d.s)(),y=function({userId:e,advisorProfileId:t,autoRequestPermission:r=!1,delayTaxReminders:a=!0}={}){let[n,d]=(0,i.useState)([]),[y,g]=(0,i.useState)(0),w=(0,i.useRef)(!1),{getUpcomingNotifications:v}=(0,m.e)({userId:e,autoLoad:!0,delayMs:a?void 0:0});!function({userId:e,advisorProfileId:t,onNotification:r}){let a=(0,i.useRef)(new Set),n=(0,i.useRef)(!0),d=(0,i.useRef)(r),m=(0,i.useRef)([]),p=(0,i.useRef)(!1),y=(0,i.useRef)(void 0),g=(0,i.useRef)(void 0);(0,i.useEffect)(()=>{d.current=r},[r]),(0,i.useEffect)(()=>{if(!e||!s.db){m.current.length>0&&(p.current=!0,m.current.forEach(e=>{try{e()}catch(e){(0,o.vV)("Cleanup subscription error (silenced):",e)}}),m.current=[],p.current=!1),y.current=void 0,g.current=void 0;return}if(y.current===e&&g.current===t&&m.current.length>0)return()=>{p.current=!0,m.current.forEach(e=>{try{e()}catch(e){(0,o.vV)("Unsubscribe error (silenced):",e)}}),m.current=[],p.current=!1,y.current=void 0,g.current=void 0};if(p.current)return;p.current=!0;let r=[...m.current];m.current=[],setTimeout(()=>{r.forEach(e=>{try{e()}catch(e){(0,o.vV)("Cleanup old subscription error (silenced):",e)}})},0),y.current=e,g.current=t;let i=(0,c.P)((0,c.rJ)(s.db,s.BOOKINGS),(0,c._M)("userId","==",e)),h=null!=t?(0,c.P)((0,c.rJ)(s.db,s.BOOKINGS),(0,c._M)("advisorId","==",t)):null,A=[],D=!1,w=setTimeout(()=>{if(y.current!==e||g.current!==t||!s.db||p.current)return;p.current=!1;let r=(0,c.aQ)(i,t=>{if(!p.current&&!D&&y.current===e)try{if(n.current){t.docs.forEach(e=>{let t=e.data();t.id=e.id;let r=`${e.id}-${t.status}-${t.updatedAt}`;if(a.current.add(r),u(t)){let e=l(t,"added");e&&d.current&&d.current(e)}}),n.current=!1;return}
20if(t.docChanges().forEach(e=>{let t=e.doc.id,r=e.doc.data();r.id=t;let i=`${t}-${r.status}-${r.updatedAt}`;if(!a.current.has(i)&&(a.current.add(i),"added"===e.type||"modified"===e.type)){let t=l(r,e.type);t&&d.current&&d.current(t)}}),a.current.size>100){let e=Array.from(a.current);a.current=new Set(e.slice(-50))}}catch(e){(0,o.vV)("處理用戶預約快照時發生錯誤:",e),D=!0}},e=>{(0,o.vV)("監聽用戶預約變化失敗:",e),D=!0;try{r()}catch(e){(0,o.vV)("清理錯誤監聽器失敗:",e)}});if(A.push(r),h){let t=(0,c.aQ)(h,t=>{if(!p.current&&!D&&y.current===e)try{if(n.current)return void t.docs.forEach(e=>{let t=e.data();t.id=e.id;let r=`advisor-${e.id}-${t.status}-${t.updatedAt}`;if(a.current.add(r),u(t)){let e=f(t,"added");e&&d.current&&d.current(e)}});if(t.docChanges().forEach(e=>{let t=e.doc.id,r=e.doc.data();r.id=t;let i=`advisor-${t}-${r.status}-${r.updatedAt}`;if(!a.current.has(i)&&(a.current.add(i),"added"===e.type||"modified"===e.type)){let t=f(r,e.type);t&&d.current&&d.current(t)}}),a.current.size>100){let e=Array.from(a.current);a.current=new Set(e.slice(-50))}}catch(e){(0,o.vV)("處理顧問預約快照時發生錯誤:",e),D=!0}},e=>{(0,o.vV)("監聽顧問預約變化失敗:",e),D=!0;try{t()}catch(e){(0,o.vV)("清理錯誤監聽器失敗:",e)}});A.push(t)}m.current=A},50);return()=>{clearTimeout(w),p.current=!0,setTimeout(()=>{let e=[...m.current];m.current=[],e.forEach(e=>{try{e()}catch(e){(0,o.vV)("Unsubscribe error (silenced):",e)}}),p.current=!1,y.current=void 0,g.current=void 0},0)}},[e,t])}({userId:e,advisorProfileId:t,onNotification:(0,i.useCallback)(e=>{d(t=>{let r=t.find(t=>t.id===e.id);if(r)return e.expiresAt&&!r.expiresAt?t.map(t=>t.id===e.id?{...t,expiresAt:e.expiresAt}:t):t;if(e.data?.type==="cancelled"&&e.data?.bookingId){let r=e.data.bookingId,a=t.filter(e=>!e.data?.bookingId||e.data.bookingId!==r||"pending"!==e.data.type&&"authorized"!==e.data.type);return[{id:e.id,title:e.title,message:e.message,createdAt:e.createdAt,expiresAt:e.expiresAt,read:!1,data:e.data},...a].slice(0,20)}return D(),[{id:e.id,title:e.title,message:e.message,createdAt:e.createdAt,expiresAt:e.expiresAt,read:!1,data:e.data},...t].slice(0,20)})},[])}),(0,i.useEffect)(()=>{if(!w.current)try{let e=localStorage.getItem(A);if(e){let t=JSON.parse(e);if(Array.isArray(t)){let e=new Date,r=new Date(e.getTime()-2592e6),a=t.filter(e=>new Date(e.createdAt)>=r).filter(t=>{if(!t.expiresAt)return!0;try{return new Date(t.expiresAt)>e}catch{return!0}}).map(e=>({...e,expiresAt:e.expiresAt||void 0,read:void 0===e.read||e.read})),i=a.filter(e=>{let t=a.filter(e=>e.data?.type==="cancelled"&&e.data?.bookingId);return!((e.data?.type==="pending"||e.data?.type==="authorized")&&e.data?.bookingId)||!t.some(t=>t.data?.bookingId===e.data?.bookingId)});d(e=>{if(e.length>0){let t=new Set(e.map(e=>e.id)),r=i.filter(e=>!t.has(e.id));return[...e,...r].slice(0,20)}return i}),w.current=!0}}else w.current=!0}catch(e){(0,o.vV)("載入通知快取失敗",e),w.current=!0}},[]);let S=(0,i.useRef)(!1),b=(0,i.useCallback)((e,t)=>{let r=t.createdAt?.toDate?.()?.toISOString?.()??new Date().toISOString(),a=t.expiresAt?.toDate?.()?.toISOString?.()??void 0,i="string"==typeof t.url?t.url:void 0,n="string"==typeof t.category?t.category:"system";return{id:`${h}${e}`,title:t.title??"通知",message:t.body??"",createdAt:r,expiresAt:a,read:t.read??!1,data:{...t.data??{},url:i,category:n,source:"firestore"}}},[]);(0,i.useEffect)(()=>{if(!e||!s.db)return;S.current=!1;let t=Date.now()-2592e6,r=(0,c.P)((0,c.rJ)(s.db,"users",e,"notifications"),(0,c._M)("createdAt",">=",c.Timestamp.fromMillis(t)),(0,c.My)("createdAt","desc"),(0,c.AB)(20));return(0,c.aQ)(r,e=>{if(!S.current){S.current=!0;let t=e.docs.map(e=>b(e.id,e.data()));d(e=>{let r=new Set(e.map(e=>e.id));return[...t.filter(e=>!r.has(e.id)),...e].slice(0,20)});return}
20e.docChanges().forEach(e=>{let t=e.doc.data(),r=`${h}${e.doc.id}`,a=t.createdAt?.toDate?.()?.getTime?.()??Date.now(),i=Date.now()-a<6e4;"added"===e.type?d(a=>a.find(e=>e.id===r)?a:(!t.read&&i&&D(),[b(e.doc.id,t),...a].slice(0,20))):"modified"===e.type?d(e=>e.map(e=>e.id===r?{...e,read:t.read??!1}:e)):"removed"===e.type&&d(e=>e.filter(e=>e.id!==r))})},e=>{(0,o.vV)("Firestore notifications onSnapshot failed",e)})},[e,b]);let I=(0,i.useRef)(v);(0,i.useEffect)(()=>{I.current=v},[v]),(0,i.useEffect)(()=>{if(!e)return;let t=()=>{try{let e=I.current(),t=new Date;d(r=>{let a=new Date(t.getTime()-2592e6),i=new Set(e.map(e=>e.id)),n=r.filter(e=>e.data?.type!=="tax"?new Date(e.createdAt)>=a:!!i.has(e.id)&&new Date(e.createdAt)>=a),d=new Set(n.map(e=>e.id)),c=e.filter(e=>!d.has(e.id)),s=[...c,...n].slice(0,20);if(0===c.length){let e=new Set(r.filter(e=>e.data?.type==="tax").map(e=>e.id)),t=new Set(s.filter(e=>e.data?.type==="tax").map(e=>e.id));if(e.size===t.size&&[...e].every(e=>t.has(e)))return r}return s})}catch(e){(0,o.vV)("處理稅務提醒通知失敗:",e)}},r=setTimeout(()=>{t()},100),a=setInterval(t,6e4);return()=>{clearTimeout(r),clearInterval(a)}},[e]);let k=(0,i.useRef)(null);(0,i.useEffect)(()=>{let e=e=>{let{symbol:t,stockName:r,totalReturn:a}=e.detail,i={id:`backtest-${Date.now()}`,title:"回測完成",message:`${r||t} (${t}) 回測已完成,總報酬率:${a.toFixed(2)}%`,createdAt:new Date().toISOString(),read:!1,data:{type:"backtest-complete",symbol:t,url:"/dashboard/investments"}};k.current&&k.current(i)};return window.addEventListener("backtest-complete",e),()=>{window.removeEventListener("backtest-complete",e)}},[]),(0,i.useEffect)(()=>{g(n.filter(e=>!e.read).length)},[n]),(0,i.useEffect)(()=>{let e=setInterval(()=>{let e=new Date;d(t=>{let r=!1,a=t.map(a=>a.expiresAt&&new Date(a.expiresAt).getTime()<=e.getTime()&&(a.data?.type==="pending"||a.data?.type==="authorized")&&!t.some(e=>e.data?.type==="cancelled"&&e.data?.bookingId===a.data?.bookingId)&&a.data?.bookingId?(p.y.cancelBooking(a.data.bookingId).then(()=>{}).catch(e=>{(0,o.vV)("自動取消過期預約失敗:",e)}),r=!0,null):a).filter(e=>null!==e);return r?a:t})},1e3);return()=>clearInterval(e)},[]),(0,i.useEffect)(()=>{if(w.current)try{let e=new Date,t=new Date(e.getTime()-2592e6),r=n.filter(e=>new Date(e.createdAt)>=t);localStorage.setItem(A,JSON.stringify(r))}catch(e){(0,o.vV)("快取通知失敗",e)}},[n]);let $=(0,i.useCallback)(e=>{d(t=>t.find(t=>t.id===e.id)?t:[e,...t].slice(0,20))},[]);(0,i.useEffect)(()=>{k.current=$},[$]);let T=(0,i.useCallback)(async t=>{if(d(e=>e.map(e=>e.id===t?{...e,read:!0}:e)),t.startsWith(h)&&e&&s.db){let r=t.slice(h.length);try{await (0,c.mZ)((0,c.doc)(s.db,"users",e,"notifications",r),{read:!0,readAt:(0,c.serverTimestamp)()})}catch(e){(0,o.vV)("Mark firestore notification read failed",e)}}},[e]),x=(0,i.useCallback)(async()=>{if(d(e=>e.map(e=>({...e,read:!0}))),e&&s.db)try{let t=(0,c.P)((0,c.rJ)(s.db,"users",e,"notifications"),(0,c._M)("read","==",!1)),r=await (0,c.GG)(t);await Promise.all(r.docs.map(e=>(0,c.mZ)(e.ref,{read:!0,readAt:(0,c.serverTimestamp)()}).catch(t=>(0,o.vV)(`Mark firestore notification ${e.id} read failed`,t))))}catch(e){(0,o.vV)("Mark all firestore notifications read failed",e)}},[e]);return{notifications:n,unreadCount:y,addNotification:$,markAsRead:T,markAllAsRead:x,removeNotification:(0,i.useCallback)(e=>{d(t=>t.filter(t=>t.id!==e))},[]),clearExpiredNotifications:(0,i.useCallback)(()=>{let e=new Date;d(t=>t.filter(t=>{if(!t.expiresAt)return!0;try{return new Date(t.expiresAt)>e}catch{return!0}}))},[])}}({userId:t?.uid,advisorProfileId:r?.id??void 0,autoRequestPermission:!1,delayTaxReminders:!0});return(0,a.jsx)(S.Provider,{value:y,children:e})}function I(){return(0,i.useContext)(S)??v}}}]);

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.