{"version":3,"file":"useAnalytics.mjs","sources":["../../../src/lib/hooks/useAnalytics.ts"],"sourcesContent":["/**\n * @file Analytics Hooks\n * @description React hooks for analytics tracking with automatic page views,\n * event tracking, and consent management\n */\n\nimport { useEffect, useCallback, useRef, useMemo, useState } from 'react';\nimport type React from 'react';\nimport {\n  analytics,\n  trackEvent,\n  trackPageView,\n  trackFeature,\n  trackPerformance,\n  type AnalyticsEventType,\n  type UserProperties,\n  type ConsentCategories,\n} from '../utils/analytics';\n\n/**\n * Hook to track page views automatically\n */\nexport function usePageView(pageName?: string, properties?: Record<string, unknown>): void {\n  const tracked = useRef(false);\n  // Memoize properties to avoid unnecessary effect re-runs if caller passes unstable object\n  // Use JSON.stringify for deep comparison since properties is an object\n  const stableProperties = useMemo(\n    () => properties,\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n    [JSON.stringify(properties)]\n  );\n\n  useEffect(() => {\n    // Only track once per mount\n    if (tracked.current) return;\n    tracked.current = true;\n\n    trackPageView(pageName, stableProperties);\n  }, [pageName, stableProperties]);\n}\n\n/**\n * Hook to get event tracking function\n */\nexport function useTrackEvent(): (\n  name: string,\n  properties?: Record<string, unknown>,\n  type?: AnalyticsEventType\n) => void {\n  return useCallback(\n    (name: string, properties?: Record<string, unknown>, type?: AnalyticsEventType) => {\n      trackEvent(name, properties, type);\n    },\n    []\n  );\n}\n\n/**\n * Hook to track feature usage\n */\nexport function useTrackFeature(featureName: string): {\n  trackAction: (action: string, context?: Record<string, unknown>) => void;\n  trackView: (context?: Record<string, unknown>) => void;\n  trackInteraction: (element: string, context?: Record<string, unknown>) => void;\n} {\n  const trackAction = useCallback(\n    (action: string, context?: Record<string, unknown>) => {\n      trackFeature(featureName, action, context);\n    },\n    [featureName]\n  );\n\n  const trackView = useCallback(\n    (context?: Record<string, unknown>) => {\n      trackFeature(featureName, 'view', context);\n    },\n    [featureName]\n  );\n\n  const trackInteraction = useCallback(\n    (element: string, context?: Record<string, unknown>) => {\n      trackFeature(featureName, `interact:${element}`, context);\n    },\n    [featureName]\n  );\n\n  return { trackAction, trackView, trackInteraction };\n}\n\n/**\n * Hook to track component render performance\n *\n * @param componentName - Name of the component to track\n */\nexport function useTrackRenderPerformance(componentName: string): void {\n  // Initialize with a function to avoid calling performance.now during render\n  const renderStart = useRef<number | null>(null);\n  const renderCount = useRef(0);\n  const componentNameRef = useRef(componentName);\n\n  // Keep component name ref updated\n  // eslint-disable-next-line react-hooks/refs\n  componentNameRef.current = componentName;\n\n  // Intentionally runs on every render to measure render performance\n  useEffect(() => {\n    // Initialize renderStart on first effect run\n    if (renderStart.current === null) {\n      renderStart.current = performance.now();\n      return;\n    }\n\n    const renderTime = performance.now() - renderStart.current;\n    renderCount.current++;\n\n    // Track slow renders (> 16ms = 60fps threshold)\n    if (renderTime > 16) {\n      trackPerformance(`render:${componentNameRef.current}`, renderTime, {\n        renderCount: renderCount.current,\n        slow: true,\n      });\n    }\n\n    // Reset for next render\n    renderStart.current = performance.now();\n  }); // No dependency array - intentionally runs on every render to track render performance\n}\n\n/**\n * Hook to track interaction timing\n */\nexport function useTrackInteractionTiming(interactionName: string): {\n  startTiming: () => void;\n  endTiming: (context?: Record<string, unknown>) => void;\n  cancelTiming: () => void;\n} {\n  const startTime = useRef<number | null>(null);\n\n  const startTiming = useCallback(() => {\n    startTime.current = performance.now();\n  }, []);\n\n  const endTiming = useCallback(\n    (context?: Record<string, unknown>) => {\n      if (startTime.current === null) return;\n\n      const duration = performance.now() - startTime.current;\n      trackPerformance(`interaction:${interactionName}`, duration, context);\n      startTime.current = null;\n    },\n    [interactionName]\n  );\n\n  const cancelTiming = useCallback(() => {\n    startTime.current = null;\n  }, []);\n\n  return { startTiming, endTiming, cancelTiming };\n}\n\n/**\n * Hook to track form analytics\n */\nexport function useTrackForm(formName: string): {\n  trackFieldFocus: (fieldName: string) => void;\n  trackFieldBlur: (fieldName: string, hasValue: boolean) => void;\n  trackFieldError: (fieldName: string, error: string) => void;\n  trackSubmitAttempt: () => void;\n  trackSubmitSuccess: (context?: Record<string, unknown>) => void;\n  trackSubmitError: (error: string) => void;\n  trackAbandonment: () => void;\n} {\n  const formStartTime = useRef<number | null>(null);\n  const focusedFields = useRef<Set<string>>(new Set());\n\n  useEffect(() => {\n    formStartTime.current = Date.now();\n    // Capture refs for cleanup\n    const fieldsRef = focusedFields;\n    const timeRef = formStartTime;\n    return () => {\n      // Track abandonment if form was started but not submitted\n      const fieldsCount = fieldsRef.current.size;\n      const startTime = timeRef.current;\n      if (fieldsCount > 0) {\n        trackEvent(`form:${formName}:abandoned`, {\n          fieldsInteracted: fieldsCount,\n          timeSpent: Date.now() - (startTime ?? Date.now()),\n        });\n      }\n    };\n  }, [formName]);\n\n  const trackFieldFocus = useCallback(\n    (fieldName: string) => {\n      focusedFields.current.add(fieldName);\n      trackEvent(`form:${formName}:field_focus`, { field: fieldName });\n    },\n    [formName]\n  );\n\n  const trackFieldBlur = useCallback(\n    (fieldName: string, hasValue: boolean) => {\n      trackEvent(`form:${formName}:field_blur`, { field: fieldName, hasValue });\n    },\n    [formName]\n  );\n\n  const trackFieldError = useCallback(\n    (fieldName: string, error: string) => {\n      trackEvent(`form:${formName}:field_error`, { field: fieldName, error });\n    },\n    [formName]\n  );\n\n  const trackSubmitAttempt = useCallback(() => {\n    trackEvent(`form:${formName}:submit_attempt`, {\n      fieldsInteracted: focusedFields.current.size,\n      timeSpent: Date.now() - (formStartTime.current ?? Date.now()),\n    });\n  }, [formName]);\n\n  const trackSubmitSuccess = useCallback(\n    (context?: Record<string, unknown>) => {\n      focusedFields.current.clear(); // Clear to prevent abandonment tracking\n      trackEvent(`form:${formName}:submit_success`, {\n        timeSpent: Date.now() - (formStartTime.current ?? Date.now()),\n        ...context,\n      });\n    },\n    [formName]\n  );\n\n  const trackSubmitError = useCallback(\n    (error: string) => {\n      trackEvent(`form:${formName}:submit_error`, { error });\n    },\n    [formName]\n  );\n\n  const trackAbandonment = useCallback(() => {\n    trackEvent(`form:${formName}:abandoned`, {\n      fieldsInteracted: focusedFields.current.size,\n      timeSpent: Date.now() - (formStartTime.current ?? Date.now()),\n    });\n    focusedFields.current.clear();\n  }, [formName]);\n\n  return {\n    trackFieldFocus,\n    trackFieldBlur,\n    trackFieldError,\n    trackSubmitAttempt,\n    trackSubmitSuccess,\n    trackSubmitError,\n    trackAbandonment,\n  };\n}\n\n/**\n * Hook for click tracking\n */\nexport function useTrackClick(\n  eventName: string,\n  properties?: Record<string, unknown>\n): (event?: React.MouseEvent) => void {\n  return useCallback(\n    (event?: React.MouseEvent) => {\n      trackEvent(\n        eventName,\n        {\n          ...properties,\n          element: event?.currentTarget?.tagName?.toLowerCase(),\n          coordinates: event ? { x: event.clientX, y: event.clientY } : undefined,\n        },\n        'click'\n      );\n    },\n    [eventName, properties]\n  );\n}\n\n/**\n * Hook to manage analytics consent\n */\nexport function useAnalyticsConsent(): {\n  consent: ConsentCategories;\n  setConsent: (consent: Partial<ConsentCategories>) => void;\n  acceptAll: () => void;\n  rejectAll: () => void;\n  hasConsented: boolean;\n} {\n  const consent = useMemo(() => analytics.getConsent(), []);\n\n  const setConsent = useCallback((newConsent: Partial<ConsentCategories>) => {\n    analytics.setConsent(newConsent);\n  }, []);\n\n  const acceptAll = useCallback(() => {\n    analytics.setConsent({\n      necessary: true,\n      analytics: true,\n      marketing: true,\n      preferences: true,\n    });\n  }, []);\n\n  const rejectAll = useCallback(() => {\n    analytics.setConsent({\n      necessary: true,\n      analytics: false,\n      marketing: false,\n      preferences: false,\n    });\n  }, []);\n\n  const hasConsented = consent.analytics || consent.marketing;\n\n  return { consent, setConsent, acceptAll, rejectAll, hasConsented };\n}\n\n/**\n * Hook to identify user for analytics\n */\nexport function useAnalyticsIdentify(): (userId: string, properties?: UserProperties) => void {\n  return useCallback((userId: string, properties?: UserProperties) => {\n    analytics.identify(userId, properties);\n  }, []);\n}\n\n/**\n * Hook to reset analytics (for logout)\n */\nexport function useAnalyticsReset(): () => void {\n  return useCallback(() => {\n    analytics.reset();\n  }, []);\n}\n\n/**\n * Hook to track search queries\n */\nexport function useTrackSearch(searchContext: string): {\n  trackSearch: (query: string, resultsCount: number) => void;\n  trackSearchClick: (query: string, resultIndex: number, resultId: string) => void;\n  trackNoResults: (query: string) => void;\n} {\n  const trackSearch = useCallback(\n    (query: string, resultsCount: number) => {\n      trackEvent(\n        `search:${searchContext}`,\n        {\n          query: query.substring(0, 100), // Truncate for privacy\n          queryLength: query.length,\n          resultsCount,\n        },\n        'search'\n      );\n    },\n    [searchContext]\n  );\n\n  const trackSearchClick = useCallback(\n    (query: string, resultIndex: number, resultId: string) => {\n      trackEvent(\n        `search:${searchContext}:click`,\n        {\n          queryLength: query.length,\n          resultIndex,\n          resultId,\n        },\n        'click'\n      );\n    },\n    [searchContext]\n  );\n\n  const trackNoResults = useCallback(\n    (query: string) => {\n      trackEvent(\n        `search:${searchContext}:no_results`,\n        {\n          queryLength: query.length,\n          queryPreview: query.substring(0, 20),\n        },\n        'search'\n      );\n    },\n    [searchContext]\n  );\n\n  return { trackSearch, trackSearchClick, trackNoResults };\n}\n\n/**\n * Hook to track scroll depth\n */\nexport function useTrackScrollDepth(pageName: string): void {\n  const trackedDepths = useRef<Set<number>>(new Set());\n\n  useEffect(() => {\n    const milestones = [25, 50, 75, 100];\n\n    const handleScroll = (): void => {\n      const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;\n      const scrollTop = window.scrollY;\n      const scrollPercent = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0;\n\n      for (const milestone of milestones) {\n        if (scrollPercent >= milestone && !trackedDepths.current.has(milestone)) {\n          trackedDepths.current.add(milestone);\n          trackEvent(`scroll:${pageName}`, {\n            depth: milestone,\n          });\n        }\n      }\n    };\n\n    window.addEventListener('scroll', handleScroll, { passive: true });\n    return () => window.removeEventListener('scroll', handleScroll);\n  }, [pageName]);\n}\n\n// Default intervals for time on page tracking - stable reference\nconst DEFAULT_TIME_INTERVALS = [30, 60, 120, 300];\n\n/**\n * Hook to track time on page\n */\nexport function useTrackTimeOnPage(\n  pageName: string,\n  intervals: number[] = DEFAULT_TIME_INTERVALS\n): void {\n  const trackedIntervals = useRef<Set<number>>(new Set());\n  // Memoize intervals to avoid effect re-runs if caller passes unstable reference\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  const stableIntervals = useMemo(() => intervals, [JSON.stringify(intervals)]);\n\n  useEffect(() => {\n    const startTime = Date.now();\n\n    const checkInterval = setInterval(() => {\n      const elapsed = (Date.now() - startTime) / 1000;\n\n      for (const interval of stableIntervals) {\n        if (elapsed >= interval && !trackedIntervals.current.has(interval)) {\n          trackedIntervals.current.add(interval);\n          trackEvent(`time_on_page:${pageName}`, {\n            seconds: interval,\n          });\n        }\n      }\n    }, 5000);\n\n    return () => {\n      clearInterval(checkInterval);\n\n      // Track final time on unmount\n      const finalTime = (Date.now() - startTime) / 1000;\n      trackEvent(`time_on_page:${pageName}:exit`, {\n        seconds: Math.round(finalTime),\n      });\n    };\n  }, [pageName, stableIntervals]);\n}\n\n/**\n * Hook to create a tracked section\n */\nexport function useTrackedSection(sectionName: string): {\n  sectionRef: React.RefObject<HTMLElement | null>;\n  isVisible: boolean;\n  viewDuration: number;\n} {\n  const sectionRef = useRef<HTMLElement>(null);\n  const isVisible = useRef(false);\n  const viewStart = useRef<number | null>(null);\n  const totalDuration = useRef(0);\n  const [viewDuration, setViewDuration] = useState(0);\n\n  useEffect(() => {\n    if (sectionRef.current === null || sectionRef.current === undefined) return;\n\n    const observer = new IntersectionObserver(\n      (entries) => {\n        const [entry] = entries;\n        if (entry === undefined || entry === null) return;\n\n        if (entry.isIntersecting && !isVisible.current) {\n          isVisible.current = true;\n          viewStart.current = Date.now();\n\n          trackEvent(`section:${sectionName}:enter`);\n        } else if (!entry.isIntersecting && isVisible.current) {\n          isVisible.current = false;\n\n          if (viewStart.current !== null && viewStart.current !== undefined) {\n            const duration = Date.now() - viewStart.current;\n            totalDuration.current += duration;\n            setViewDuration(totalDuration.current);\n\n            trackEvent(`section:${sectionName}:exit`, {\n              viewDuration: duration,\n              totalDuration: totalDuration.current,\n            });\n          }\n        }\n      },\n      { threshold: 0.5 }\n    );\n\n    observer.observe(sectionRef.current);\n\n    return () => {\n      observer.disconnect();\n\n      // Track final duration on unmount\n      if (isVisible.current && viewStart.current !== null && viewStart.current !== undefined) {\n        const duration = Date.now() - viewStart.current;\n        trackEvent(`section:${sectionName}:unmount`, {\n          viewDuration: duration,\n          totalDuration: totalDuration.current + duration,\n        });\n      }\n    };\n  }, [sectionName]);\n\n  return {\n    sectionRef,\n    // eslint-disable-next-line react-hooks/refs\n    isVisible: isVisible.current,\n    viewDuration,\n  };\n}\n"],"names":["usePageView","pageName","properties","tracked","useRef","stableProperties","useMemo","useEffect","trackPageView","useTrackEvent","useCallback","name","type","trackEvent","useTrackFeature","featureName","trackAction","action","context","trackFeature","trackView","trackInteraction","element","useTrackRenderPerformance","componentName","renderStart","renderCount","componentNameRef","renderTime","trackPerformance","useTrackInteractionTiming","interactionName","startTime","startTiming","endTiming","duration","cancelTiming","useTrackForm","formName","formStartTime","focusedFields","fieldsRef","timeRef","fieldsCount","trackFieldFocus","fieldName","trackFieldBlur","hasValue","trackFieldError","error","trackSubmitAttempt","trackSubmitSuccess","trackSubmitError","trackAbandonment","useTrackClick","eventName","event","useAnalyticsConsent","consent","analytics","setConsent","newConsent","acceptAll","rejectAll","hasConsented","useAnalyticsIdentify","userId","useAnalyticsReset","useTrackSearch","searchContext","trackSearch","query","resultsCount","trackSearchClick","resultIndex","resultId","trackNoResults","useTrackScrollDepth","trackedDepths","milestones","handleScroll","scrollHeight","scrollTop","scrollPercent","milestone","DEFAULT_TIME_INTERVALS","useTrackTimeOnPage","intervals","trackedIntervals","stableIntervals","checkInterval","elapsed","interval","finalTime","useTrackedSection","sectionName","sectionRef","isVisible","viewStart","totalDuration","viewDuration","setViewDuration","useState","observer","entries","entry"],"mappings":"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"}