// src/hooks/useProfileEvents.js // 个人资料和设置事件追踪 Hook import { useCallback } from 'react'; import { usePostHogTrack } from './usePostHogRedux'; import { RETENTION_EVENTS } from '../lib/constants'; import { logger } from '../utils/logger'; /** * 个人资料和设置事件追踪 Hook * @param {Object} options - 配置选项 * @param {string} options.pageType - 页面类型 ('profile' | 'settings' | 'security') * @returns {Object} 事件追踪处理函数集合 */ export const useProfileEvents = ({ pageType = 'profile' } = {}) => { const { track } = usePostHogTrack(); /** * 追踪个人资料字段编辑开始 * @param {string} fieldName - 字段名称 ('nickname' | 'email' | 'phone' | 'avatar' | 'bio') */ const trackProfileFieldEditStarted = useCallback((fieldName) => { if (!fieldName) { logger.warn('useProfileEvents', 'trackProfileFieldEditStarted: fieldName is required'); return; } track('Profile Field Edit Started', { field_name: fieldName, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '✏️ Profile Field Edit Started', { fieldName, pageType, }); }, [track, pageType]); /** * 追踪个人资料更新成功 * @param {Array} updatedFields - 更新的字段列表 * @param {Object} changes - 变更详情 */ const trackProfileUpdated = useCallback((updatedFields = [], changes = {}) => { if (!updatedFields || updatedFields.length === 0) { logger.warn('useProfileEvents', 'trackProfileUpdated: updatedFields array is required'); return; } track(RETENTION_EVENTS.PROFILE_UPDATED, { updated_fields: updatedFields, field_count: updatedFields.length, changes: changes, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '✅ Profile Updated', { updatedFields, fieldCount: updatedFields.length, pageType, }); }, [track, pageType]); /** * 追踪个人资料更新失败 * @param {Array} attemptedFields - 尝试更新的字段 * @param {string} errorMessage - 错误信息 */ const trackProfileUpdateFailed = useCallback((attemptedFields = [], errorMessage = '') => { track('Profile Update Failed', { attempted_fields: attemptedFields, error_message: errorMessage, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '❌ Profile Update Failed', { attemptedFields, errorMessage, pageType, }); }, [track, pageType]); /** * 追踪头像上传 * @param {string} uploadMethod - 上传方式 ('file_upload' | 'url' | 'camera' | 'default_avatar') * @param {number} fileSize - 文件大小(bytes) */ const trackAvatarUploaded = useCallback((uploadMethod = 'file_upload', fileSize = 0) => { track('Avatar Uploaded', { upload_method: uploadMethod, file_size: fileSize, file_size_mb: (fileSize / (1024 * 1024)).toFixed(2), page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '🖼️ Avatar Uploaded', { uploadMethod, fileSize, pageType, }); }, [track, pageType]); /** * 追踪密码更改 * @param {boolean} success - 是否成功 * @param {string} errorReason - 失败原因 */ const trackPasswordChanged = useCallback((success = true, errorReason = '') => { track('Password Changed', { success, error_reason: errorReason || null, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', success ? '🔒 Password Changed Successfully' : '❌ Password Change Failed', { success, errorReason, pageType, }); }, [track, pageType]); /** * 追踪邮箱验证发起 * @param {string} email - 邮箱地址 */ const trackEmailVerificationSent = useCallback((email = '') => { track('Email Verification Sent', { email_provided: Boolean(email), page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '📧 Email Verification Sent', { emailProvided: Boolean(email), pageType, }); }, [track, pageType]); /** * 追踪手机号验证发起 * @param {string} phone - 手机号 */ const trackPhoneVerificationSent = useCallback((phone = '') => { track('Phone Verification Sent', { phone_provided: Boolean(phone), page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '📱 Phone Verification Sent', { phoneProvided: Boolean(phone), pageType, }); }, [track, pageType]); /** * 追踪账号绑定(微信、邮箱、手机等) * @param {string} accountType - 账号类型 ('wechat' | 'email' | 'phone') * @param {boolean} success - 是否成功 */ const trackAccountBound = useCallback((accountType, success = true) => { if (!accountType) { logger.warn('useProfileEvents', 'trackAccountBound: accountType is required'); return; } track('Account Bound', { account_type: accountType, success, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', success ? '🔗 Account Bound' : '❌ Account Bind Failed', { accountType, success, pageType, }); }, [track, pageType]); /** * 追踪账号解绑 * @param {string} accountType - 账号类型 * @param {boolean} success - 是否成功 */ const trackAccountUnbound = useCallback((accountType, success = true) => { if (!accountType) { logger.warn('useProfileEvents', 'trackAccountUnbound: accountType is required'); return; } track('Account Unbound', { account_type: accountType, success, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', success ? '🔓 Account Unbound' : '❌ Account Unbind Failed', { accountType, success, pageType, }); }, [track, pageType]); /** * 追踪设置项更改 * @param {string} settingName - 设置名称 * @param {any} oldValue - 旧值 * @param {any} newValue - 新值 * @param {string} category - 设置分类 ('notification' | 'privacy' | 'display' | 'advanced') */ const trackSettingChanged = useCallback((settingName, oldValue, newValue, category = 'general') => { if (!settingName) { logger.warn('useProfileEvents', 'trackSettingChanged: settingName is required'); return; } track(RETENTION_EVENTS.SETTINGS_CHANGED, { setting_name: settingName, old_value: String(oldValue), new_value: String(newValue), category, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '⚙️ Setting Changed', { settingName, oldValue, newValue, category, pageType, }); }, [track, pageType]); /** * 追踪通知偏好更改 * @param {Object} preferences - 通知偏好设置 * @param {boolean} preferences.email - 邮件通知 * @param {boolean} preferences.push - 推送通知 * @param {boolean} preferences.sms - 短信通知 */ const trackNotificationPreferencesChanged = useCallback((preferences = {}) => { track('Notification Preferences Changed', { email_enabled: preferences.email || false, push_enabled: preferences.push || false, sms_enabled: preferences.sms || false, total_enabled: Object.values(preferences).filter(Boolean).length, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '🔔 Notification Preferences Changed', { preferences, pageType, }); }, [track, pageType]); /** * 追踪隐私设置更改 * @param {string} privacySetting - 隐私设置名称 * @param {boolean} isPublic - 是否公开 */ const trackPrivacySettingChanged = useCallback((privacySetting, isPublic = false) => { if (!privacySetting) { logger.warn('useProfileEvents', 'trackPrivacySettingChanged: privacySetting is required'); return; } track('Privacy Setting Changed', { privacy_setting: privacySetting, is_public: isPublic, page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '🔐 Privacy Setting Changed', { privacySetting, isPublic, pageType, }); }, [track, pageType]); /** * 追踪账号删除请求 * @param {string} reason - 删除原因 */ const trackAccountDeletionRequested = useCallback((reason = '') => { track('Account Deletion Requested', { reason, has_reason: Boolean(reason), page_type: pageType, timestamp: new Date().toISOString(), }); logger.debug('useProfileEvents', '🗑️ Account Deletion Requested', { reason, pageType, }); }, [track, pageType]); return { // 个人资料编辑 trackProfileFieldEditStarted, trackProfileUpdated, trackProfileUpdateFailed, trackAvatarUploaded, // 安全和验证 trackPasswordChanged, trackEmailVerificationSent, trackPhoneVerificationSent, // 账号绑定 trackAccountBound, trackAccountUnbound, // 设置更改 trackSettingChanged, trackNotificationPreferencesChanged, trackPrivacySettingChanged, // 账号管理 trackAccountDeletionRequested, }; }; export default useProfileEvents;