Initial commit

This commit is contained in:
Haitham Khalifa
2026-02-16 12:18:06 +01:00
commit b538d84e17
63 changed files with 15059 additions and 0 deletions
+210
View File
@@ -0,0 +1,210 @@
'use client';
import { useAuth } from '@/contexts/AuthContext';
import { useRouter } from 'next/navigation';
import { useEffect, useState, FormEvent } from 'react';
import { getAuth, updateProfile, updatePassword } from 'firebase/auth';
import { app } from '@/lib/firebase';
export default function SettingsPage() {
const { user, isLoading } = useAuth();
const router = useRouter();
const [name, setName] = useState('');
const [currentPassword, setCurrentPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [saving, setSaving] = useState(false);
const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
useEffect(() => {
if (!isLoading && !user) {
router.push('/auth');
}
if (user) {
setName(user.name || '');
}
}, [user, isLoading, router]);
if (isLoading) {
return (
<div className="min-h-screen flex items-center justify-center bg-[#050316] text-white">
<div className="animate-pulse text-2xl">Loading...</div>
</div>
);
}
if (!user) return null;
const handleUpdateProfile = async (e: FormEvent) => {
e.preventDefault();
setSaving(true);
setMessage(null);
try {
const auth = getAuth(app);
if (auth.currentUser && name !== user.name) {
await updateProfile(auth.currentUser, { displayName: name });
setMessage({ type: 'success', text: 'Profile updated successfully!' });
}
} catch (error: any) {
setMessage({ type: 'error', text: error.message || 'Failed to update profile' });
} finally {
setSaving(false);
}
};
const handleChangePassword = async (e: FormEvent) => {
e.preventDefault();
setSaving(true);
setMessage(null);
if (newPassword !== confirmPassword) {
setMessage({ type: 'error', text: 'Passwords do not match' });
setSaving(false);
return;
}
if (newPassword.length < 6) {
setMessage({ type: 'error', text: 'Password must be at least 6 characters' });
setSaving(false);
return;
}
try {
const auth = getAuth(app);
if (auth.currentUser) {
await updatePassword(auth.currentUser, newPassword);
setMessage({ type: 'success', text: 'Password changed successfully!' });
setCurrentPassword('');
setNewPassword('');
setConfirmPassword('');
}
} catch (error: any) {
if (error.code === 'auth/requires-recent-login') {
setMessage({ type: 'error', text: 'Please log out and log back in to change your password' });
} else {
setMessage({ type: 'error', text: error.message || 'Failed to change password' });
}
} finally {
setSaving(false);
}
};
return (
<div className="min-h-screen bg-[#050316] text-white">
{/* Navigation */}
<nav className="border-b border-white/10 bg-white/5 backdrop-blur-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center space-x-8">
<h1 className="text-2xl font-bold">HolaCompi</h1>
<button
onClick={() => router.push('/dashboard')}
className="text-gray-400 hover:text-white transition-colors"
>
Back to Dashboard
</button>
</div>
</div>
</div>
</nav>
<main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="space-y-8">
<div>
<h2 className="text-3xl font-bold mb-2">Account Settings</h2>
<p className="text-gray-400">Manage your profile and account preferences</p>
</div>
{/* Success/Error Message */}
{message && (
<div
className={`rounded-lg px-4 py-3 ${
message.type === 'success'
? 'bg-green-500/10 border border-green-500/20 text-green-400'
: 'bg-red-500/10 border border-red-500/20 text-red-400'
}`}
>
{message.text}
</div>
)}
{/* Account Info */}
<div className="bg-white/5 rounded-2xl border border-white/10 p-6">
<h3 className="text-xl font-semibold mb-4">Account Information</h3>
<div className="space-y-3">
<div>
<label className="text-sm text-gray-400">Email</label>
<p className="text-white">{user.email}</p>
</div>
<div>
<label className="text-sm text-gray-400">User ID</label>
<p className="text-white font-mono text-xs">{user.uid}</p>
</div>
</div>
</div>
{/* Profile Settings */}
<div className="bg-white/5 rounded-2xl border border-white/10 p-6">
<h3 className="text-xl font-semibold mb-4">Profile Settings</h3>
<form onSubmit={handleUpdateProfile} className="space-y-4">
<div>
<label className="block text-sm mb-2">Display Name</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full rounded-lg px-4 py-3 bg-black/30 border border-white/10 text-white outline-none focus:border-purple-400 transition-colors"
placeholder="Enter your name"
/>
</div>
<button
type="submit"
disabled={saving || name === user.name}
className="px-6 py-2.5 rounded-lg bg-purple-500 hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{saving ? 'Saving...' : 'Save Changes'}
</button>
</form>
</div>
{/* Change Password */}
<div className="bg-white/5 rounded-2xl border border-white/10 p-6">
<h3 className="text-xl font-semibold mb-4">Change Password</h3>
<form onSubmit={handleChangePassword} className="space-y-4">
<div>
<label className="block text-sm mb-2">New Password</label>
<input
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
className="w-full rounded-lg px-4 py-3 bg-black/30 border border-white/10 text-white outline-none focus:border-purple-400 transition-colors"
placeholder="Enter new password (min 6 characters)"
required
/>
</div>
<div>
<label className="block text-sm mb-2">Confirm New Password</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full rounded-lg px-4 py-3 bg-black/30 border border-white/10 text-white outline-none focus:border-purple-400 transition-colors"
placeholder="Confirm new password"
required
/>
</div>
<button
type="submit"
disabled={saving}
className="px-6 py-2.5 rounded-lg bg-red-500 hover:bg-red-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
{saving ? 'Changing...' : 'Change Password'}
</button>
</form>
</div>
</div>
</main>
</div>
);
}