aethex-forge/client/hooks/use-xp.ts
sirpiglr 51f0cd2c7d Award experience points for user actions and improve level-up notifications
Introduces XP awarding for post creation, daily logins, and profile completion, alongside enhanced level-up notifications and refactored profile data handling.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: ca9f859b-1a66-40d5-a421-8de34f2805fd
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/MdI1YXa
Replit-Helium-Checkpoint-Created: true
2025-12-12 23:44:00 +00:00

112 lines
3 KiB
TypeScript

import { useCallback } from "react";
import { useAuth } from "@/contexts/AuthContext";
import {
aethexXPService,
XPEventType,
XPAwardResult,
calculateLevel,
levelProgress,
xpForNextLevel,
} from "@/lib/aethex-database-adapter";
import { aethexToast } from "@/lib/aethex-toast";
export interface UseXPReturn {
awardXP: (eventType: XPEventType, multiplier?: number) => Promise<XPAwardResult>;
awardCustomXP: (amount: number, reason?: string) => Promise<XPAwardResult>;
awardStreakBonus: (streakDays: number) => Promise<XPAwardResult>;
calculateLevel: typeof calculateLevel;
levelProgress: typeof levelProgress;
xpForNextLevel: typeof xpForNextLevel;
}
export function useXP(): UseXPReturn {
const { user } = useAuth();
const showLevelUpToast = useCallback((result: XPAwardResult) => {
if (result.leveledUp) {
aethexToast.aethex({
title: `Level Up! Level ${result.newLevel}`,
description: `You've earned ${result.xpAwarded} XP and reached level ${result.newLevel}!`,
duration: 6000,
});
} else if (result.success && result.xpAwarded > 0) {
aethexToast.success({
title: `+${result.xpAwarded} XP`,
description: `Total: ${result.newTotalXp} XP`,
duration: 3000,
});
}
}, []);
const awardXP = useCallback(
async (eventType: XPEventType, multiplier: number = 1): Promise<XPAwardResult> => {
if (!user?.id) {
return {
success: false,
xpAwarded: 0,
newTotalXp: 0,
previousLevel: 1,
newLevel: 1,
leveledUp: false,
error: "Not logged in",
};
}
const result = await aethexXPService.awardXP(user.id, eventType, multiplier);
showLevelUpToast(result);
return result;
},
[user?.id, showLevelUpToast]
);
const awardCustomXP = useCallback(
async (amount: number, reason?: string): Promise<XPAwardResult> => {
if (!user?.id) {
return {
success: false,
xpAwarded: 0,
newTotalXp: 0,
previousLevel: 1,
newLevel: 1,
leveledUp: false,
error: "Not logged in",
};
}
const result = await aethexXPService.awardCustomXP(user.id, amount, reason);
showLevelUpToast(result);
return result;
},
[user?.id, showLevelUpToast]
);
const awardStreakBonus = useCallback(
async (streakDays: number): Promise<XPAwardResult> => {
if (!user?.id) {
return {
success: false,
xpAwarded: 0,
newTotalXp: 0,
previousLevel: 1,
newLevel: 1,
leveledUp: false,
error: "Not logged in",
};
}
const result = await aethexXPService.awardStreakBonus(user.id, streakDays);
showLevelUpToast(result);
return result;
},
[user?.id, showLevelUpToast]
);
return {
awardXP,
awardCustomXP,
awardStreakBonus,
calculateLevel,
levelProgress,
xpForNextLevel,
};
}