Spaces:
Configuration error
Configuration error
| // src/hooks/useUserStats.ts | |
| import { useEffect, useState } from 'react'; | |
| import { doc, onSnapshot, updateDoc, increment } from 'firebase/firestore'; | |
| import { db, auth } from '../firebase'; | |
| import { UserStats } from '../types/user'; | |
| export const useUserStats = () => { | |
| const [stats, setStats] = useState<UserStats | undefined>(undefined); | |
| useEffect(() => { | |
| if (!auth.currentUser) return; | |
| const userRef = doc(db, 'users', auth.currentUser.uid); | |
| const unsubscribe = onSnapshot(userRef, async (docSnap) => { | |
| if (docSnap.exists()) { | |
| const data = docSnap.data(); | |
| // Ensure stats exist | |
| let userStats: UserStats = data.stats || { | |
| textsHumanized: 0, | |
| wordsProcessed: 0, | |
| gptAverage: 0, | |
| totalSessions: 0, | |
| totalDuration: 0, | |
| averageSessionTime: 0, | |
| }; | |
| // Backfill totalDuration if missing | |
| if (userStats.totalDuration === undefined) { | |
| const estimatedDuration = | |
| (userStats.averageSessionTime ?? 0) * (userStats.totalSessions ?? 1); | |
| await updateDoc(userRef, { 'stats.totalDuration': estimatedDuration }); | |
| userStats.totalDuration = estimatedDuration; | |
| } | |
| // Always recalc averageSessionTime | |
| const avgTime = | |
| (userStats.totalSessions && userStats.totalDuration) | |
| ? userStats.totalDuration / userStats.totalSessions | |
| : 0; | |
| userStats.averageSessionTime = avgTime; | |
| setStats(userStats); | |
| } | |
| }); | |
| return () => unsubscribe(); | |
| }, []); | |
| const updateStats = async (newStats: Partial<UserStats>) => { | |
| if (!auth.currentUser || !stats) return; | |
| const userRef = doc(db, 'users', auth.currentUser.uid); | |
| // Calculate new totalDuration if averageSessionTime or totalSessions are updated | |
| let updatedTotalDuration = stats.totalDuration; | |
| let updatedTotalSessions = stats.totalSessions; | |
| if (newStats.totalSessions !== undefined) { | |
| updatedTotalSessions += newStats.totalSessions; | |
| } | |
| if (newStats.averageSessionTime !== undefined) { | |
| updatedTotalDuration = updatedTotalSessions * newStats.averageSessionTime; | |
| } else if (newStats.totalDuration !== undefined) { | |
| updatedTotalDuration = stats.totalDuration + newStats.totalDuration; | |
| } | |
| const newAvgSessionTime = | |
| updatedTotalSessions > 0 ? updatedTotalDuration / updatedTotalSessions : 0; | |
| await updateDoc(userRef, { | |
| 'stats.textsHumanized': | |
| newStats.textsHumanized !== undefined | |
| ? increment(newStats.textsHumanized) | |
| : increment(0), | |
| 'stats.wordsProcessed': | |
| newStats.wordsProcessed !== undefined | |
| ? increment(newStats.wordsProcessed) | |
| : increment(0), | |
| 'stats.totalSessions': | |
| newStats.totalSessions !== undefined | |
| ? increment(newStats.totalSessions) | |
| : increment(0), | |
| 'stats.gptAverage': | |
| newStats.gptAverage !== undefined ? newStats.gptAverage : stats.gptAverage, | |
| 'stats.totalDuration': updatedTotalDuration, | |
| 'stats.averageSessionTime': newAvgSessionTime, | |
| }); | |
| }; | |
| return { stats, updateStats }; | |
| }; | |