159 lines
8.4 KiB
TypeScript
159 lines
8.4 KiB
TypeScript
|
|
import { useState, useEffect } from 'react';
|
||
|
|
import { Settings, User, Bell, Shield, Palette, Globe } from 'lucide-react';
|
||
|
|
import { Button } from '@/components/ui/button';
|
||
|
|
import { useAuthStore } from '@/features/auth/store/authStore';
|
||
|
|
import { useUIStore } from '@/stores/ui';
|
||
|
|
import { useToast } from '@/hooks/useToast';
|
||
|
|
import { ThemeSwitcher } from '@/components/theme/ThemeSwitcher';
|
||
|
|
|
||
|
|
export function SettingsPage() {
|
||
|
|
const { user } = useAuthStore();
|
||
|
|
const { theme, setTheme, language, setLanguage } = useUIStore();
|
||
|
|
const { toast } = useToast();
|
||
|
|
const [activeTab, setActiveTab] = useState('profile');
|
||
|
|
const [colorTheme, setColorTheme] = useState('cyber');
|
||
|
|
|
||
|
|
// Apply color theme to document
|
||
|
|
useEffect(() => {
|
||
|
|
document.documentElement.setAttribute('data-color-theme', colorTheme);
|
||
|
|
}, [colorTheme]);
|
||
|
|
|
||
|
|
const handleThemeChange = (newTheme: string) => {
|
||
|
|
setColorTheme(newTheme);
|
||
|
|
toast({ title: 'Theme Changed', description: `Switched to ${newTheme} theme` });
|
||
|
|
};
|
||
|
|
|
||
|
|
const tabs = [
|
||
|
|
{ id: 'profile', label: 'Profile', icon: User },
|
||
|
|
{ id: 'notifications', label: 'Notifications', icon: Bell },
|
||
|
|
{ id: 'privacy', label: 'Privacy', icon: Shield },
|
||
|
|
{ id: 'appearance', label: 'Appearance', icon: Palette },
|
||
|
|
{ id: 'language', label: 'Language', icon: Globe },
|
||
|
|
];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="min-h-screen p-6 space-y-6">
|
||
|
|
{/* Header */}
|
||
|
|
<div className="glass-hud rounded-2xl border-white/10 p-6 hud-corner">
|
||
|
|
<div className="flex items-center gap-3">
|
||
|
|
<div className="w-12 h-12 rounded-xl bg-kodo-cyan/20 flex items-center justify-center border border-kodo-cyan/30">
|
||
|
|
<Settings className="w-6 h-6 text-kodo-cyan" />
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<h1 className="text-2xl font-display font-bold text-white">Settings</h1>
|
||
|
|
<p className="text-sm text-kodo-secondary">Manage your account preferences</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
||
|
|
{/* Sidebar */}
|
||
|
|
<div className="glass-hud rounded-xl border-white/10 p-4 h-fit">
|
||
|
|
<nav className="space-y-1">
|
||
|
|
{tabs.map((tab) => {
|
||
|
|
const Icon = tab.icon;
|
||
|
|
return (
|
||
|
|
<button
|
||
|
|
key={tab.id}
|
||
|
|
onClick={() => setActiveTab(tab.id)}
|
||
|
|
className={`w-full flex items-center gap-3 px-4 py-3 rounded-lg transition-all ${activeTab === tab.id
|
||
|
|
? 'bg-kodo-cyan/10 text-kodo-cyan border border-kodo-cyan/30'
|
||
|
|
: 'text-kodo-secondary hover:text-white hover:bg-white/5'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
<Icon className="w-4 h-4" />
|
||
|
|
<span className="text-sm font-medium">{tab.label}</span>
|
||
|
|
</button>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</nav>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Content */}
|
||
|
|
<div className="lg:col-span-3 glass-hud rounded-xl border-white/10 p-6">
|
||
|
|
{activeTab === 'profile' && (
|
||
|
|
<div className="space-y-6">
|
||
|
|
<h2 className="text-xl font-bold text-white">Profile Settings</h2>
|
||
|
|
<div className="space-y-4">
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-white mb-2">Username</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
defaultValue={user?.username}
|
||
|
|
className="w-full px-4 py-2 bg-kodo-graphite border border-white/10 rounded-lg text-white focus:border-kodo-cyan focus:outline-none"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-white mb-2">Email</label>
|
||
|
|
<input
|
||
|
|
type="email"
|
||
|
|
defaultValue={user?.email}
|
||
|
|
className="w-full px-4 py-2 bg-kodo-graphite border border-white/10 rounded-lg text-white focus:border-kodo-cyan focus:outline-none"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<Button className="bg-kodo-cyan hover:bg-kodo-cyan/80 text-black" onClick={() => toast({ title: 'Saved!', description: 'Profile settings updated successfully' })}>
|
||
|
|
Save Changes
|
||
|
|
</Button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{activeTab === 'appearance' && (
|
||
|
|
<div className="space-y-6">
|
||
|
|
<h2 className="text-xl font-bold text-white">Appearance</h2>
|
||
|
|
|
||
|
|
<ThemeSwitcher currentTheme={colorTheme} onThemeChange={handleThemeChange} />
|
||
|
|
|
||
|
|
<div className="border-t border-white/10 pt-6 mt-6">
|
||
|
|
<label className="block text-sm font-medium text-white mb-2">Light/Dark Mode</label>
|
||
|
|
<div className="grid grid-cols-3 gap-3">
|
||
|
|
{['light', 'dark', 'system'].map((t) => (
|
||
|
|
<button
|
||
|
|
key={t}
|
||
|
|
onClick={() => setTheme(t as 'light' | 'dark' | 'system')}
|
||
|
|
className={`px-4 py-3 rounded-lg border transition-all ${theme === t
|
||
|
|
? 'bg-kodo-cyan/10 border-kodo-cyan text-kodo-cyan'
|
||
|
|
: 'border-white/10 text-kodo-secondary hover:border-white/20'
|
||
|
|
}`}
|
||
|
|
>
|
||
|
|
{t.charAt(0).toUpperCase() + t.slice(1)}
|
||
|
|
</button>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{activeTab === 'language' && (
|
||
|
|
<div className="space-y-6">
|
||
|
|
<h2 className="text-xl font-bold text-white">Language</h2>
|
||
|
|
<div className="space-y-4">
|
||
|
|
<div>
|
||
|
|
<label className="block text-sm font-medium text-white mb-2">Preferred Language</label>
|
||
|
|
<select
|
||
|
|
value={language}
|
||
|
|
onChange={(e) => setLanguage(e.target.value as 'en' | 'fr')}
|
||
|
|
className="w-full px-4 py-2 bg-kodo-graphite border border-white/10 rounded-lg text-white focus:border-kodo-cyan focus:outline-none"
|
||
|
|
>
|
||
|
|
<option value="en">English</option>
|
||
|
|
<option value="fr">Français</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{(activeTab === 'notifications' || activeTab === 'privacy') && (
|
||
|
|
<div className="space-y-6">
|
||
|
|
<h2 className="text-xl font-bold text-white">
|
||
|
|
{activeTab === 'notifications' ? 'Notifications' : 'Privacy'}
|
||
|
|
</h2>
|
||
|
|
<p className="text-kodo-secondary">Settings for {activeTab} will be available soon.</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|