gaialive's picture
Upload 106 files
759768a verified
// Enhanced Authentication System with Local Storage
class AuthManager {
constructor() {
this.baseStorageKeys = {
user: 'ecospire_user',
activities: 'ecospire_activities',
stats: 'ecospire_stats',
settings: 'ecospire_settings'
};
this.initializeStorage();
}
// Get user-specific storage keys
getStorageKeys(userId = null) {
const currentUser = userId || this.getCurrentUserId();
if (!currentUser || currentUser === 'guest') {
return this.baseStorageKeys;
}
return {
user: this.baseStorageKeys.user,
activities: `${this.baseStorageKeys.activities}_${currentUser}`,
stats: `${this.baseStorageKeys.stats}_${currentUser}`,
settings: `${this.baseStorageKeys.settings}_${currentUser}`
};
}
getCurrentUserId() {
const userData = localStorage.getItem(this.baseStorageKeys.user);
if (userData) {
const user = JSON.parse(userData);
return user.id;
}
return null;
}
initializeStorage() {
// Initialize default data if not exists
if (!localStorage.getItem(this.baseStorageKeys.user)) {
this.setGuestMode();
}
// Initialize user-specific data
const keys = this.getStorageKeys();
if (!localStorage.getItem(keys.activities)) {
localStorage.setItem(keys.activities, JSON.stringify([]));
}
if (!localStorage.getItem(keys.stats)) {
this.resetStats();
}
}
setGuestMode() {
const guestUser = {
id: 'guest',
name: 'Guest User',
email: 'guest@p4cng.biz.vn',
isGuest: true,
joinDate: new Date().toISOString(),
avatar: '🌱',
location: null,
preferences: {
notifications: true,
publicProfile: false,
dataSharing: false
}
};
localStorage.setItem(this.baseStorageKeys.user, JSON.stringify(guestUser));
}
resetStats() {
const defaultStats = {
carbonSaved: 0,
waterTests: 0,
biodiversityScans: 0,
wasteReduced: 0,
energySaved: 0,
treesPlanted: 0,
totalActivities: 0,
streakDays: 0,
lastActivity: null,
achievements: [],
level: 1,
points: 0
};
const keys = this.getStorageKeys();
localStorage.setItem(keys.stats, JSON.stringify(defaultStats));
}
getCurrentUser() {
const userData = localStorage.getItem(this.baseStorageKeys.user);
return userData ? JSON.parse(userData) : null;
}
isAuthenticated() {
const user = this.getCurrentUser();
return user && !user.isGuest;
}
isGuestMode() {
const user = this.getCurrentUser();
return user && user.isGuest;
}
getUserStats() {
const keys = this.getStorageKeys();
const statsData = localStorage.getItem(keys.stats);
if (statsData) {
return JSON.parse(statsData);
} else {
this.resetStats();
return JSON.parse(localStorage.getItem(keys.stats));
}
}
updateUserStats(updates) {
const currentStats = this.getUserStats();
const newStats = { ...currentStats, ...updates };
// Update level based on points
newStats.level = Math.floor(newStats.points / 1000) + 1;
// Update streak
const today = new Date().toDateString();
const lastActivity = newStats.lastActivity ? new Date(newStats.lastActivity).toDateString() : null;
if (lastActivity !== today) {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
if (lastActivity === yesterday.toDateString()) {
newStats.streakDays += 1;
} else if (lastActivity !== today) {
newStats.streakDays = 1;
}
newStats.lastActivity = new Date().toISOString();
}
const keys = this.getStorageKeys();
localStorage.setItem(keys.stats, JSON.stringify(newStats));
return newStats;
}
async logActivity(description, data = {}) {
const activities = this.getActivities();
const activity = {
id: Date.now(),
timestamp: new Date().toISOString(),
description,
data,
type: data.type || 'general',
points: data.points || 10
};
activities.unshift(activity);
// Keep only last 100 activities
if (activities.length > 100) {
activities.splice(100);
}
const keys = this.getStorageKeys();
localStorage.setItem(keys.activities, JSON.stringify(activities));
// Update stats
const currentStats = this.getUserStats();
const updates = {
totalActivities: currentStats.totalActivities + 1,
points: currentStats.points + activity.points
};
// Update specific stats based on activity type
switch (data.type) {
case 'water_test':
updates.waterTests = (currentStats.waterTests || 0) + (data.amount || 1);
break;
case 'biodiversity_scan':
updates.biodiversityScans = (currentStats.biodiversityScans || 0) + (data.amount || 1);
break;
case 'carbon_reduction':
updates.carbonSaved = (currentStats.carbonSaved || 0) + (data.amount || 1);
break;
case 'waste_reduction':
updates.wasteReduced = (currentStats.wasteReduced || 0) + (data.amount || 1);
break;
case 'energy_saved':
updates.energySaved = (currentStats.energySaved || 0) + (data.amount || 1);
break;
case 'tree_planted':
updates.treesPlanted = (currentStats.treesPlanted || 0) + (data.amount || 1);
break;
case 'general':
// General activities don't update specific counters but still give points
break;
}
this.updateUserStats(updates);
this.checkAchievements();
return { success: true, id: activity.id, activity };
}
getActivities(limit = 50) {
const keys = this.getStorageKeys();
const activities = localStorage.getItem(keys.activities);
const allActivities = activities ? JSON.parse(activities) : [];
return allActivities.slice(0, limit);
}
async getUserData(type, limit = 10) {
const activities = this.getActivities();
return activities
.filter(activity => activity.type === type)
.slice(0, limit)
.map(activity => ({
...activity.data,
timestamp: activity.timestamp
}));
}
checkAchievements() {
try {
const stats = this.getUserStats();
// Ensure stats is valid and has required properties
if (!stats || typeof stats !== 'object') {
console.warn('Invalid stats object in checkAchievements');
return [];
}
// Ensure achievements array exists
if (!Array.isArray(stats.achievements)) {
stats.achievements = [];
}
const newAchievements = [];
// Define achievements
const achievements = [
{ id: 'first_test', name: 'First Test', description: 'Complete your first water test', condition: () => (stats.waterTests || 0) >= 1, icon: 'πŸ’§' },
{ id: 'bio_explorer', name: 'Bio Explorer', description: 'Complete 5 biodiversity scans', condition: () => (stats.biodiversityScans || 0) >= 5, icon: '🦜' },
{ id: 'carbon_saver', name: 'Carbon Saver', description: 'Save 10kg of COβ‚‚', condition: () => (stats.carbonSaved || 0) >= 10, icon: '🌱' },
{ id: 'streak_week', name: 'Weekly Streak', description: 'Maintain a 7-day activity streak', condition: () => (stats.streakDays || 0) >= 7, icon: 'πŸ”₯' },
{ id: 'level_up', name: 'Level Up', description: 'Reach level 5', condition: () => (stats.level || 1) >= 5, icon: '⭐' },
{ id: 'eco_champion', name: 'Eco Champion', description: 'Complete 50 activities', condition: () => (stats.totalActivities || 0) >= 50, icon: 'πŸ†' }
];
achievements.forEach(achievement => {
try {
if (achievement.condition() && !stats.achievements.includes(achievement.id)) {
newAchievements.push(achievement);
stats.achievements.push(achievement.id);
}
} catch (error) {
console.warn(`Error checking achievement ${achievement.id}:`, error);
}
});
if (newAchievements.length > 0) {
const keys = this.getStorageKeys();
localStorage.setItem(keys.stats, JSON.stringify(stats));
return newAchievements;
}
return [];
} catch (error) {
console.error('Error in checkAchievements:', error);
return [];
}
}
async login(credentials) {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
// For demo, create a user based on email
const user = {
id: credentials.email.replace('@', '_').replace(/\./g, '_'),
name: credentials.name || credentials.email.split('@')[0],
email: credentials.email,
isGuest: false,
joinDate: new Date().toISOString(),
avatar: this.generateAvatar(credentials.email),
location: null,
preferences: {
notifications: true,
publicProfile: true,
dataSharing: true
}
};
// Store the new user
localStorage.setItem(this.baseStorageKeys.user, JSON.stringify(user));
// Initialize user-specific data storage
this.initializeUserData(user.id);
return { success: true, user };
}
initializeUserData(userId) {
const keys = this.getStorageKeys(userId);
// Initialize activities if they don't exist
if (!localStorage.getItem(keys.activities)) {
localStorage.setItem(keys.activities, JSON.stringify([]));
}
// Initialize stats if they don't exist
if (!localStorage.getItem(keys.stats)) {
const defaultStats = {
carbonSaved: 0,
waterTests: 0,
biodiversityScans: 0,
wasteReduced: 0,
energySaved: 0,
treesPlanted: 0,
totalActivities: 0,
streakDays: 0,
lastActivity: null,
achievements: [],
level: 1,
points: 0
};
localStorage.setItem(keys.stats, JSON.stringify(defaultStats));
}
}
async register(userData) {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1500));
const user = {
id: userData.email.replace('@', '_').replace(/\./g, '_'),
name: userData.name,
email: userData.email,
isGuest: false,
joinDate: new Date().toISOString(),
avatar: this.generateAvatar(userData.email),
location: null,
preferences: {
notifications: true,
publicProfile: true,
dataSharing: true
}
};
localStorage.setItem(this.baseStorageKeys.user, JSON.stringify(user));
// Initialize fresh user data
this.initializeUserData(user.id);
return { success: true, user };
}
async logout() {
// Log the logout activity before clearing
await this.logActivity('User logged out', {
type: 'auth',
action: 'logout',
points: 0
});
// Clear current user and reset to guest mode
this.setGuestMode();
return { success: true };
}
generateAvatar(email) {
const avatars = ['🌱', '🌿', '🌳', '🦜', '🐝', '🌸', '🌺', 'πŸƒ', '🌾', '🌻'];
const index = email.charCodeAt(0) % avatars.length;
return avatars[index];
}
updateUserProfile(updates) {
const user = this.getCurrentUser();
if (user) {
const updatedUser = { ...user, ...updates };
localStorage.setItem(this.baseStorageKeys.user, JSON.stringify(updatedUser));
return updatedUser;
}
return null;
}
getLeaderboard() {
// Simulate leaderboard data
const currentUser = this.getCurrentUser();
const currentStats = this.getUserStats();
return [
{ name: 'EcoChampion2024', points: 15420, level: 16, avatar: 'πŸ†' },
{ name: 'GreenWarrior', points: 12890, level: 13, avatar: '🌱' },
{ name: 'BioDiversityExpert', points: 11250, level: 12, avatar: '🦜' },
{ name: currentUser?.name || 'You', points: currentStats.points, level: currentStats.level, avatar: currentUser?.avatar || '🌿', isCurrentUser: true },
{ name: 'WaterTester', points: 8940, level: 9, avatar: 'πŸ’§' },
{ name: 'CarbonSaver', points: 7650, level: 8, avatar: '🌳' },
{ name: 'EcoNewbie', points: 3420, level: 4, avatar: '🌸' }
].sort((a, b) => b.points - a.points);
}
}
export const authManager = new AuthManager();
export default authManager;