- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid - Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px) - Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation - Modified files across all components to ensure consistent 8px grid alignment - Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
280 lines
9.9 KiB
TypeScript
280 lines
9.9 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Card } from '../../ui/card';
|
|
import { Button } from '../../ui/button';
|
|
import { useTheme } from '../../../context/ThemeContext';
|
|
import { ThemeVariant } from '../../../types';
|
|
import {
|
|
Mail,
|
|
User,
|
|
Globe,
|
|
Bell,
|
|
Lock,
|
|
ShieldAlert,
|
|
Monitor,
|
|
Moon,
|
|
Sun,
|
|
Laptop,
|
|
} from 'lucide-react';
|
|
import { ChangeEmailModal } from './ChangeEmailModal';
|
|
import { ChangeUsernameModal } from './ChangeUsernameModal';
|
|
import { DeleteAccountView } from './DeleteAccountView';
|
|
import { useToast } from '../../../context/ToastContext';
|
|
import { Switch } from '../../ui/switch';
|
|
|
|
export const AccountSettings: React.FC = () => {
|
|
const { theme, setTheme } = useTheme();
|
|
const { addToast } = useToast();
|
|
|
|
// State for sub-views and modals
|
|
const [view, setView] = useState<'main' | 'delete'>('main');
|
|
const [showEmailModal, setShowEmailModal] = useState(false);
|
|
const [showUsernameModal, setShowUsernameModal] = useState(false);
|
|
|
|
// Mock User Data
|
|
const [user] = useState({
|
|
username: 'Cyber_Producer',
|
|
email: 'alex@veza.io',
|
|
language: 'English (US)',
|
|
});
|
|
|
|
// Toggles State
|
|
const [toggles, setToggles] = useState({
|
|
emailNotif: true,
|
|
pushNotif: true,
|
|
publicProfile: true,
|
|
showActivity: true,
|
|
});
|
|
|
|
const toggle = (key: keyof typeof toggles) => {
|
|
setToggles((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
addToast('Settings updated', 'info');
|
|
};
|
|
|
|
if (view === 'delete') {
|
|
return (
|
|
<DeleteAccountView
|
|
onBack={() => setView('main')}
|
|
onLogout={() => window.location.reload()}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-8 animate-fadeIn max-w-4xl mx-auto pb-10">
|
|
{/* 1. IDENTITY SECTION */}
|
|
<Card variant="default">
|
|
<h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
|
|
<User className="w-5 h-5 text-kodo-steel" /> Identity & Login
|
|
</h3>
|
|
|
|
<div className="space-y-6">
|
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 p-4 bg-kodo-ink rounded-lg border border-kodo-steel/50">
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-10 h-10 bg-kodo-slate rounded-full flex items-center justify-center text-kodo-content-dim">
|
|
<Mail className="w-5 h-5" />
|
|
</div>
|
|
<div>
|
|
<div className="text-sm font-bold text-white">
|
|
Email Address
|
|
</div>
|
|
<div className="text-xs text-kodo-content-dim">{user.email}</div>
|
|
</div>
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="border border-kodo-steel"
|
|
onClick={() => setShowEmailModal(true)}
|
|
>
|
|
Change Email
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 p-4 bg-kodo-ink rounded-lg border border-kodo-steel/50">
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-10 h-10 bg-kodo-slate rounded-full flex items-center justify-center text-kodo-content-dim">
|
|
<User className="w-5 h-5" />
|
|
</div>
|
|
<div>
|
|
<div className="text-sm font-bold text-white">Username</div>
|
|
<div className="text-xs text-kodo-content-dim">@{user.username}</div>
|
|
</div>
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="border border-kodo-steel"
|
|
onClick={() => setShowUsernameModal(true)}
|
|
>
|
|
Change Username
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
{/* 2. PREFERENCES SECTION */}
|
|
<Card variant="default">
|
|
<h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
|
|
<Monitor className="w-5 h-5 text-kodo-magenta" /> Preferences
|
|
</h3>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
<div>
|
|
<label className="block text-sm font-bold text-kodo-content-dim mb-3">
|
|
Interface Theme
|
|
</label>
|
|
<div className="grid grid-cols-3 gap-2">
|
|
{[
|
|
{
|
|
id: ThemeVariant.NEON,
|
|
label: 'Dark',
|
|
icon: <Moon className="w-4 h-4" />,
|
|
},
|
|
{
|
|
id: ThemeVariant.LIGHT,
|
|
label: 'Light',
|
|
icon: <Sun className="w-4 h-4" />,
|
|
},
|
|
{
|
|
id: ThemeVariant.GAMING,
|
|
label: 'Game',
|
|
icon: <Laptop className="w-4 h-4" />,
|
|
},
|
|
].map((opt) => (
|
|
<button
|
|
key={opt.id}
|
|
onClick={() => setTheme(opt.id)}
|
|
className={`flex flex-col items-center justify-center gap-2 p-4 rounded-lg border transition-all ${theme === opt.id ? 'bg-kodo-cyan/10 border-kodo-cyan text-kodo-cyan' : 'bg-kodo-ink border-kodo-steel text-kodo-content-dim hover:text-white'}`}
|
|
>
|
|
{opt.icon}
|
|
<span className="text-xs font-bold">{opt.label}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-bold text-kodo-content-dim mb-3">
|
|
Language
|
|
</label>
|
|
<div className="relative">
|
|
<Globe className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-kodo-content-dim" />
|
|
<select className="w-full bg-kodo-ink border border-kodo-steel rounded-lg py-2.5 pl-10 pr-4 text-white text-sm focus:border-kodo-steel outline-none appearance-none cursor-pointer hover:border-kodo-steel transition-colors">
|
|
<option>English (US)</option>
|
|
<option>Japanese</option>
|
|
<option>French</option>
|
|
<option>Spanish</option>
|
|
<option>German</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
{/* 3. NOTIFICATIONS & PRIVACY */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
<Card variant="default">
|
|
<h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
|
|
<Bell className="w-5 h-5 text-kodo-lime" /> Notifications
|
|
</h3>
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-sm text-kodo-text-main">Email Notifications</span>
|
|
<Switch
|
|
checked={toggles.emailNotif}
|
|
onChange={() => toggle('emailNotif')}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-sm text-kodo-text-main">Push Notifications</span>
|
|
<Switch
|
|
checked={toggles.pushNotif}
|
|
onChange={() => toggle('pushNotif')}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
|
|
<Card variant="default">
|
|
<h3 className="text-lg font-bold text-white mb-6 flex items-center gap-2">
|
|
<Lock className="w-5 h-5 text-kodo-gold" /> Privacy
|
|
</h3>
|
|
<div className="space-y-4">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<span className="text-sm text-kodo-text-main block">
|
|
Public Profile
|
|
</span>
|
|
<span className="text-[10px] text-kodo-content-dim">
|
|
Allow others to find you
|
|
</span>
|
|
</div>
|
|
<Switch
|
|
checked={toggles.publicProfile}
|
|
onChange={() => toggle('publicProfile')}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<span className="text-sm text-kodo-text-main block">
|
|
Activity Status
|
|
</span>
|
|
<span className="text-[10px] text-kodo-content-dim">
|
|
Show when you are online
|
|
</span>
|
|
</div>
|
|
<Switch
|
|
checked={toggles.showActivity}
|
|
onChange={() => toggle('showActivity')}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* 4. DANGER ZONE */}
|
|
<Card
|
|
variant="default"
|
|
className="border-kodo-red/30 relative overflow-hidden"
|
|
>
|
|
<div className="absolute top-0 left-0 w-1 h-full bg-kodo-red"></div>
|
|
<h3 className="text-lg font-bold text-white mb-2 flex items-center gap-2">
|
|
<ShieldAlert className="w-5 h-5 text-kodo-red" /> Danger Zone
|
|
</h3>
|
|
<p className="text-kodo-content-dim text-sm mb-6">
|
|
Irreversible actions. Proceed with caution.
|
|
</p>
|
|
|
|
<div className="flex flex-col md:flex-row items-center justify-between gap-4 p-4 bg-kodo-red/5 rounded border border-kodo-red/20">
|
|
<div>
|
|
<div className="font-bold text-white text-sm">Delete Account</div>
|
|
<div className="text-xs text-kodo-content-dim">
|
|
Permanently remove your account and all data.
|
|
</div>
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
className="text-kodo-red hover:bg-kodo-red hover:text-white border border-kodo-red/50 w-full md:w-auto"
|
|
onClick={() => setView('delete')}
|
|
>
|
|
DELETE ACCOUNT
|
|
</Button>
|
|
</div>
|
|
</Card>
|
|
|
|
{/* MODALS */}
|
|
{showEmailModal && (
|
|
<ChangeEmailModal
|
|
onClose={() => setShowEmailModal(false)}
|
|
currentEmail={user.email}
|
|
/>
|
|
)}
|
|
{showUsernameModal && (
|
|
<ChangeUsernameModal
|
|
onClose={() => setShowUsernameModal(false)}
|
|
currentUsername={user.username}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|