deckhearth/pages/settings.js

670 lines
27 KiB
JavaScript
Raw Normal View History

🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import Layout from '../components/Layout';
export default function Settings() {
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
const router = useRouter();
// User state
fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) * convoy: scope fix-layout-default-user (P0 #7 — Layout maintainer-email leak) The last remaining P0 ship-blocker from .convoys/ship-readiness.md. components/Layout.js line 562 defaults the user prop to a real email address (me@randallstillwell.com); any page that renders Layout without passing user explicitly impersonates the maintainer. Scope: components/Layout.js + audit of 17 pages that import Layout (grep-confirmed list in convoy file). Single PR likely. Auditor cohort skipped (no design-system, IA, or browser-smoke surface). Architect to address: - Q1: logged-out rendering branch design (navbar, mobile-nav, auth-only items treatment) - Q2: page audit triage into always-auth / public-or-auth / anonymous-allowed buckets - Q3: brief decomposition (single brief / 2 briefs in 1 PR / fan-out) - Q4: whether to add vitest coverage for the logged-out branch (recommend yes — small surface, high regression protection) Hard out-of-scope: branding (pick-a-name), auth-provider collapse (single-auth-provider), Layout god-component split (god-component-split). depends_on: bump-next-js (shipped), fix-auth-bypass (shipped), drop-public-setup (shipped) addresses: P0 #7 from .convoys/ship-readiness.md parent: ship-readiness Co-authored-by: Cursor <cursoragent@cursor.com> * architect(fix-layout-default-user): plan + briefs 1-2 (Layout fix + page audit) 2 briefs, single PR. ~12 files net (down from the 18 in the original scope — 10 of the 17 Layout-importing pages already pass user explicitly). Brief 1: components/Layout.js default user=null + Sign-in CTA branch in UserProfileDropdown when logged out. Adds first jsdom test in the repo at test/components/Layout.test.js (Decision D2) with 5 regression-lock assertions. devDeps: jsdom@^29, @testing-library/react@^16. Brief 2: page audit sweep — 7 pages need code changes: - Pass user={user} to Layout: scanner.js, deck-builder.js (×4), deck/[id].js (×3), decks.js (×3) - Replace page-level useState({email: 'me@...'}) → useState(null) + null-guards: profile.js, settings.js - Replace hardcoded const user = {email: 'me@...'} with useAuth(): card/[id].js Discovered second anti-pattern: profile.js, settings.js, card/[id].js seed page-level state with the maintainer email. Folded into Brief 2 since success metric "no real email address remains in any component default-prop" reads naturally to include page-level seed values. Decisions: A1 — Sign-in CTA replaces avatar+email+dropdown when user===null; hides auth-only dropdown (Profile/Settings/Logout/Admin); keeps public + community nav visible B — Per-page bucket assignment (10 already correct, 7 need fix); full per-page table with justification in convoy file C2 — Two briefs in one PR (Brief 1 = Layout + test; Brief 2 = page sweep depends on Brief 1). C1 buries the conceptual change under mechanical edits; C3 is over-orchestrated for this scope D2 — vitest lock-in; first jsdom test in repo; same negative-regression style as test/lib/permission-middleware.test.js (synthetic-admin shape). devDeps jsdom + @testing-library/react Risks tracked R1-R8. Biggest: R2 (useState(null) null-deref in 3 leaky pages — mitigated by audit-pass mandate + manual smoke). MobileNavigation deliberately NOT folded in: its user prop is dead code (never reads user.*); different bug class; cleanup queued separately to avoid scope expansion. Flagged-but-deferred: - 4 pages still import useAuth from lib/auth-context.js → single-auth-provider (queued P1 #9) - Layout headers still render "Deck Hearth" / "DH" branding → pick-a-name (queued P1 #12) - MobileNavigation dead user prop → cleanup-mobile-nav-dead-props or fold into god-component-split addresses: P0 #7 from .convoys/ship-readiness.md (last P0 ship-blocker) parent: ship-readiness Co-authored-by: Cursor <cursoragent@cursor.com> * feat(layout): default user=null + Sign-in CTA when logged out (Brief 1 of fix-layout-default-user) Closes the source-side half of P0 #7 from .convoys/ship-readiness.md. The page-side sweep (Brief 2) follows in a separate commit. components/Layout.js: - Default user prop is now null (was hardcoded to { email: 'me@randallstillwell.com', role: 'user' }) - UserProfileDropdown renders a "Sign in" link to /login when user === null instead of the maintainer's email + auth-only menu items (Decision A1) - All user.* accesses guarded with optional chaining or null checks - useState hook stays above the new null-user early return to satisfy rules-of-hooks (boot-the-brief caught this on the first try; see AGENTS.md Gotcha #11.5) test/components/Layout.test.js (new): - First jsdom test in the repo (Decision D2) - 5 regression-lock assertions: no maintainer email ever rendered (prop omitted, prop=null), Sign-in link exists with href=/login, supplied email renders when prop is set, no "Guest" placeholder (locks A1 copy choice) - Mocks next/link, next/router (prefetch, replace, events, query), and theme-context.useTheme for jsdom safety under Next 16 package.json + package-lock.json: - Add jsdom@^29 and @testing-library/react@^16 to devDependencies - @testing-library/dom@^10 added explicitly (peer auto-install skipped it under npm 11; brief anticipated this fallback) vitest.config.js (deviation from brief — see PR description): - Add esbuild { loader: 'jsx', jsx: 'automatic' } so vitest can parse JSX in .js files. Required to import any React component written in the repo's Next.js pages-router .js convention (AGENTS.md Gotcha #9). The brief said "no change" to this file, but JSX-in-.js parsing is a hard prerequisite for the new test to import components/Layout.js — the alternatives (rename test to .test.jsx; rewrite test in React.createElement) either break the test glob or still hit the same Layout.js parse failure. Other tests are unaffected (they import non-JSX modules). Smoke output: see PR description. addresses: P0 #7 from .convoys/ship-readiness.md (last P0 ship-blocker) Co-authored-by: Cursor <cursoragent@cursor.com> * feat(pages): pass user explicitly + null-guard leaky page seeds (Brief 2 of fix-layout-default-user) Closes the page-side half of P0 #7 from .convoys/ship-readiness.md. Brief 1 (commit ddf8fd2) handled the Layout-side fix. Per the architect's per-page bucket table (Decision B in .convoys/fix-layout-default-user.md), 7 pages needed code changes; the other 10 of 17 Layout-importing pages already pass `user` correctly. Pass user={user} to Layout (4 pages, 11 call sites): - pages/scanner.js (1 call) - pages/decks.js (3 calls) - pages/deck-builder.js (4 calls) - pages/deck/[id].js (3 calls) (All four still import useAuth from lib/auth-context.js — that's intentional and stays as-is until the single-auth-provider convoy collapses the three parallel auth surfaces.) Replace leaky page-level seed values with useState(null) + null guards (2 pages, R2 mitigation): - pages/profile.js: useState({email: 'me@...', role: 'user', ...}) → useState(null) + ?. on every sync user.* read + early-return guards in getDisplayName/getInitials + conditional render around the "Member since" block so formatDate(undefined) never runs - pages/settings.js: same pattern (single user.email reader guarded) Replace hardcoded const with useAuth from lib/use-auth.js (1 page): - pages/card/[id].js: const user = {email: 'me@...'} → const { user } = useAuth() (called unconditionally at the top of the component; rules-of-hooks safe) Verification: - grep 'me@randallstillwell.com' pages/ → 0 hits - 21/21 vitest tests pass (16 pre-existing + 5 from Brief 1) - npm run lint matches baseline (128 problems pre, 128 post; verified via git stash before/after) - Manual static read-through of every diff; ReadLints clean on the 7 files - Dev-server smoke: /cards anonymous returned HTTP 200 with 0 'me@randallstillwell' matches before the user's shared dev server became unresponsive mid-session (same dev-server-shared-by-user constraint flagged in Brief 1); interactive logged-in smoke is parent/operator gated Flagged-but-deferred (untouched per scope): - 4 pages still import useAuth from lib/auth-context.js → single-auth-provider (queued P1 #9) - components/MobileNavigation.js still receives dead user prop → cleanup-mobile-nav-dead-props (or fold into god-component-split) addresses: P0 #7 from .convoys/ship-readiness.md (last P0 ship-blocker) Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 15:31:37 -04:00
const [user, setUser] = useState(null);
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
// Settings state
const [settings, setSettings] = useState({
// Account Settings
notifications_email: true,
notifications_marketing: false,
collection_visibility: 'private',
preferred_currency: 'USD',
cards_per_page: 50,
default_view: 'grid',
// Security Settings
two_factor_enabled: false,
// Display Settings
theme: 'system', // light, dark, system
language: 'en'
});
// Password change state
const [passwordForm, setPasswordForm] = useState({
current_password: '',
new_password: '',
confirm_password: ''
});
// UI state
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [changingPassword, setChangingPassword] = useState(false);
const [message, setMessage] = useState({ type: '', text: '' });
const [activeSection, setActiveSection] = useState('account');
const loadSettings = async () => {
try {
const token = localStorage.getItem('auth_token');
if (!token) {
router.push('/login');
return;
}
const response = await fetch('/api/user/settings', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
const data = await response.json();
setUser(data.user);
setSettings(data.settings);
} else if (response.status === 401) {
router.push('/login');
}
} catch (error) {
console.error('Error loading settings:', error);
setMessage({ type: 'error', text: 'Failed to load settings' });
} finally {
setLoading(false);
}
}
useEffect(() => {
// eslint-disable-next-line react-hooks/set-state-in-effect -- load settings on mount
loadSettings();
// eslint-disable-next-line react-hooks/exhaustive-deps -- mount-only settings load
}, []);
;
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
const handleSettingChange = (key, value) => {
setSettings(prev => ({
...prev,
[key]: value
}));
};
const saveSettings = async () => {
setSaving(true);
setMessage({ type: '', text: '' });
try {
const token = localStorage.getItem('auth_token');
const response = await fetch('/api/user/settings', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(settings)
});
if (response.ok) {
setMessage({ type: 'success', text: 'Settings saved successfully!' });
} else {
const error = await response.json();
setMessage({ type: 'error', text: error.message || 'Failed to save settings' });
}
} catch (error) {
console.error('Error saving settings:', error);
setMessage({ type: 'error', text: 'Failed to save settings' });
} finally {
setSaving(false);
}
};
const handlePasswordChange = async (e) => {
e.preventDefault();
if (passwordForm.new_password !== passwordForm.confirm_password) {
setMessage({ type: 'error', text: 'New passwords do not match' });
return;
}
if (passwordForm.new_password.length < 8) {
setMessage({ type: 'error', text: 'Password must be at least 8 characters long' });
return;
}
setChangingPassword(true);
setMessage({ type: '', text: '' });
try {
const token = localStorage.getItem('auth_token');
const response = await fetch('/api/user/password', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({
current_password: passwordForm.current_password,
new_password: passwordForm.new_password
})
});
if (response.ok) {
setPasswordForm({ current_password: '', new_password: '', confirm_password: '' });
setMessage({ type: 'success', text: 'Password changed successfully!' });
} else {
const error = await response.json();
setMessage({ type: 'error', text: error.message || 'Failed to change password' });
}
} catch (error) {
console.error('Error changing password:', error);
setMessage({ type: 'error', text: 'Failed to change password' });
} finally {
setChangingPassword(false);
}
};
const handleDeleteAccount = async () => {
const confirmed = window.confirm(
'Are you sure you want to delete your account? This action cannot be undone and will permanently delete all your cards, lists, and decks.'
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
);
if (!confirmed) return;
const doubleConfirmed = window.confirm(
'This is your final warning. Deleting your account will permanently remove all your data. Type "DELETE" to confirm.'
);
if (!doubleConfirmed) return;
try {
const token = localStorage.getItem('auth_token');
const response = await fetch('/api/user/delete', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
localStorage.removeItem('auth_token');
router.push('/login?message=Account deleted successfully');
} else {
const error = await response.json();
setMessage({ type: 'error', text: error.message || 'Failed to delete account' });
}
} catch (error) {
console.error('Error deleting account:', error);
setMessage({ type: 'error', text: 'Failed to delete account' });
}
};
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
const sections = [
{ id: 'account', name: 'Account', icon: '👤' },
{ id: 'security', name: 'Security', icon: '🔒' },
{ id: 'preferences', name: 'Preferences', icon: '⚙️' },
{ id: 'notifications', name: 'Notifications', icon: '🔔' },
{ id: 'display', name: 'Display', icon: '🎨' }
];
const currencyOptions = [
{ value: 'USD', label: 'US Dollar ($)' },
{ value: 'EUR', label: 'Euro (€)' },
{ value: 'GBP', label: 'British Pound (£)' },
{ value: 'CAD', label: 'Canadian Dollar (C$)' },
{ value: 'JPY', label: 'Japanese Yen (¥)' }
];
const cardsPerPageOptions = [
{ value: 25, label: '25 cards' },
{ value: 50, label: '50 cards' },
{ value: 100, label: '100 cards' }
];
const viewOptions = [
{ value: 'grid', label: 'Grid View' },
{ value: 'list', label: 'List View' }
];
const themeOptions = [
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' },
{ value: 'system', label: 'System' }
];
if (loading) {
return (
<Layout user={user}>
<div className="flex items-center justify-center min-h-screen">
<div className="animate-spin rounded-full h-32 w-32 border-b-2" style={{ borderColor: 'var(--accent-ember)' }}></div>
</div>
</Layout>
);
}
return (
<Layout user={user}>
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
<div className="max-w-6xl mx-auto p-6">
{/* Header */}
<div className="mb-8">
<h1 className="text-3xl font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
Settings
</h1>
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
<p className="text-lg" style={{ color: 'var(--text-secondary)' }}>
Manage your account preferences and security settings
</p>
</div>
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
{/* Message */}
{message.text && (
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
<div
className="mb-6 p-4 rounded-xl glass-panel"
style={{
color:
message.type === 'success' ? 'var(--accent-flame)' : '#dc2626',
borderColor:
message.type === 'success' ? 'var(--accent-flame)' : '#dc2626',
}}
>
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
{message.text}
</div>
)}
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
{/* Sidebar Navigation */}
<div className="lg:col-span-1">
refactor(styles): retire .card; migrate 7 consumers to .glass-panel (#122) Brief 5 of unify-glass-panel-surfaces convoy. Deletes the legacy .card class from styles/globals.css and migrates all consumers (actual count: 7, not 8 as the brief had estimated — one of the suspected sites was already on a different pattern) to .glass-panel rounded-3xl p-{4|6}. A single panel vocabulary across the app — .glass-panel for body content, .glass-panel-strong for floating chrome/popovers, .page-header-glass for full-bleed top strips — is the convoy's success metric. .card predated the gradient-border system and was the only remaining "opaque solid panel" pattern in user-facing pages. Consumers migrated: - pages/settings.js × 2 (p-4 and p-6 cards) - pages/profile.js × 3 (avatar card, stats card, activity card) - pages/community/collections.js × 1 - components/CollectionsPageView.js × 1 Each migration: - Replaces `card` with `glass-panel rounded-3xl` in the className. - Preserves sibling Tailwind tokens (p-4 / p-6 / text-center / mt-6 / group / cursor-pointer). - Adds `transition-all duration-{200|300}` explicitly where the legacy class baked it in (5 of 7 sites needed this back). - Drops hover:shadow-{lg,xl} Tailwind overrides on the 2 community sites; the .glass-panel corner-light gradient is the new affordance. CSS change in styles/globals.css: - Removed the `.card { @apply rounded-3xl shadow-lg p-6 transition-all duration-300; background-color: var(--bg-primary); border: 1px solid var(--border); }` rule. - Added a documentation comment in its place explaining the retirement and pointing future consumers at the right alternative. Verification: - rg "className=[\"'\`]card\b" pages/ components/ --type js returns 0 matches. - rg "^\.card \{" styles/ returns 0 matches. - npm run lint passes (1 pre-existing warning unrelated). - npm run test:run: 113/113 tests pass. Acceptance criteria from .convoys/unify-glass-panel-surfaces/brief-5-retire-card-class.md all met. No escape-hatch sites needed; all 7 migrations were clean. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 16:30:29 -04:00
<div className="glass-panel rounded-3xl p-4 transition-all duration-300">
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
<nav className="space-y-2">
{sections.map(section => (
<button
key={section.id}
onClick={() => setActiveSection(section.id)}
refactor(design): site-wide sweep — broken Tailwind tokens, rounded corners, SearchBar primitive (#117) (#117) Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 15:06:22 -04:00
className={`nav-item w-full flex items-center gap-3 px-4 py-3 font-medium text-left ${
activeSection === section.id ? 'nav-item-active' : 'nav-item-hover'
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
}`}
>
<span>{section.icon}</span>
{section.name}
</button>
))}
</nav>
</div>
</div>
{/* Settings Content */}
<div className="lg:col-span-3">
refactor(styles): retire .card; migrate 7 consumers to .glass-panel (#122) Brief 5 of unify-glass-panel-surfaces convoy. Deletes the legacy .card class from styles/globals.css and migrates all consumers (actual count: 7, not 8 as the brief had estimated — one of the suspected sites was already on a different pattern) to .glass-panel rounded-3xl p-{4|6}. A single panel vocabulary across the app — .glass-panel for body content, .glass-panel-strong for floating chrome/popovers, .page-header-glass for full-bleed top strips — is the convoy's success metric. .card predated the gradient-border system and was the only remaining "opaque solid panel" pattern in user-facing pages. Consumers migrated: - pages/settings.js × 2 (p-4 and p-6 cards) - pages/profile.js × 3 (avatar card, stats card, activity card) - pages/community/collections.js × 1 - components/CollectionsPageView.js × 1 Each migration: - Replaces `card` with `glass-panel rounded-3xl` in the className. - Preserves sibling Tailwind tokens (p-4 / p-6 / text-center / mt-6 / group / cursor-pointer). - Adds `transition-all duration-{200|300}` explicitly where the legacy class baked it in (5 of 7 sites needed this back). - Drops hover:shadow-{lg,xl} Tailwind overrides on the 2 community sites; the .glass-panel corner-light gradient is the new affordance. CSS change in styles/globals.css: - Removed the `.card { @apply rounded-3xl shadow-lg p-6 transition-all duration-300; background-color: var(--bg-primary); border: 1px solid var(--border); }` rule. - Added a documentation comment in its place explaining the retirement and pointing future consumers at the right alternative. Verification: - rg "className=[\"'\`]card\b" pages/ components/ --type js returns 0 matches. - rg "^\.card \{" styles/ returns 0 matches. - npm run lint passes (1 pre-existing warning unrelated). - npm run test:run: 113/113 tests pass. Acceptance criteria from .convoys/unify-glass-panel-surfaces/brief-5-retire-card-class.md all met. No escape-hatch sites needed; all 7 migrations were clean. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 16:30:29 -04:00
<div className="glass-panel rounded-3xl p-6 transition-all duration-300">
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
{/* Account Settings */}
{activeSection === 'account' && (
<div>
<h2 className="text-2xl font-bold mb-6" style={{ color: 'var(--text-primary)' }}>
Account Settings
</h2>
<div className="space-y-6">
{/* Email */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Email Address
</label>
<div className="flex items-center gap-3">
<input
type="email"
fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) * convoy: scope fix-layout-default-user (P0 #7 — Layout maintainer-email leak) The last remaining P0 ship-blocker from .convoys/ship-readiness.md. components/Layout.js line 562 defaults the user prop to a real email address (me@randallstillwell.com); any page that renders Layout without passing user explicitly impersonates the maintainer. Scope: components/Layout.js + audit of 17 pages that import Layout (grep-confirmed list in convoy file). Single PR likely. Auditor cohort skipped (no design-system, IA, or browser-smoke surface). Architect to address: - Q1: logged-out rendering branch design (navbar, mobile-nav, auth-only items treatment) - Q2: page audit triage into always-auth / public-or-auth / anonymous-allowed buckets - Q3: brief decomposition (single brief / 2 briefs in 1 PR / fan-out) - Q4: whether to add vitest coverage for the logged-out branch (recommend yes — small surface, high regression protection) Hard out-of-scope: branding (pick-a-name), auth-provider collapse (single-auth-provider), Layout god-component split (god-component-split). depends_on: bump-next-js (shipped), fix-auth-bypass (shipped), drop-public-setup (shipped) addresses: P0 #7 from .convoys/ship-readiness.md parent: ship-readiness Co-authored-by: Cursor <cursoragent@cursor.com> * architect(fix-layout-default-user): plan + briefs 1-2 (Layout fix + page audit) 2 briefs, single PR. ~12 files net (down from the 18 in the original scope — 10 of the 17 Layout-importing pages already pass user explicitly). Brief 1: components/Layout.js default user=null + Sign-in CTA branch in UserProfileDropdown when logged out. Adds first jsdom test in the repo at test/components/Layout.test.js (Decision D2) with 5 regression-lock assertions. devDeps: jsdom@^29, @testing-library/react@^16. Brief 2: page audit sweep — 7 pages need code changes: - Pass user={user} to Layout: scanner.js, deck-builder.js (×4), deck/[id].js (×3), decks.js (×3) - Replace page-level useState({email: 'me@...'}) → useState(null) + null-guards: profile.js, settings.js - Replace hardcoded const user = {email: 'me@...'} with useAuth(): card/[id].js Discovered second anti-pattern: profile.js, settings.js, card/[id].js seed page-level state with the maintainer email. Folded into Brief 2 since success metric "no real email address remains in any component default-prop" reads naturally to include page-level seed values. Decisions: A1 — Sign-in CTA replaces avatar+email+dropdown when user===null; hides auth-only dropdown (Profile/Settings/Logout/Admin); keeps public + community nav visible B — Per-page bucket assignment (10 already correct, 7 need fix); full per-page table with justification in convoy file C2 — Two briefs in one PR (Brief 1 = Layout + test; Brief 2 = page sweep depends on Brief 1). C1 buries the conceptual change under mechanical edits; C3 is over-orchestrated for this scope D2 — vitest lock-in; first jsdom test in repo; same negative-regression style as test/lib/permission-middleware.test.js (synthetic-admin shape). devDeps jsdom + @testing-library/react Risks tracked R1-R8. Biggest: R2 (useState(null) null-deref in 3 leaky pages — mitigated by audit-pass mandate + manual smoke). MobileNavigation deliberately NOT folded in: its user prop is dead code (never reads user.*); different bug class; cleanup queued separately to avoid scope expansion. Flagged-but-deferred: - 4 pages still import useAuth from lib/auth-context.js → single-auth-provider (queued P1 #9) - Layout headers still render "Deck Hearth" / "DH" branding → pick-a-name (queued P1 #12) - MobileNavigation dead user prop → cleanup-mobile-nav-dead-props or fold into god-component-split addresses: P0 #7 from .convoys/ship-readiness.md (last P0 ship-blocker) parent: ship-readiness Co-authored-by: Cursor <cursoragent@cursor.com> * feat(layout): default user=null + Sign-in CTA when logged out (Brief 1 of fix-layout-default-user) Closes the source-side half of P0 #7 from .convoys/ship-readiness.md. The page-side sweep (Brief 2) follows in a separate commit. components/Layout.js: - Default user prop is now null (was hardcoded to { email: 'me@randallstillwell.com', role: 'user' }) - UserProfileDropdown renders a "Sign in" link to /login when user === null instead of the maintainer's email + auth-only menu items (Decision A1) - All user.* accesses guarded with optional chaining or null checks - useState hook stays above the new null-user early return to satisfy rules-of-hooks (boot-the-brief caught this on the first try; see AGENTS.md Gotcha #11.5) test/components/Layout.test.js (new): - First jsdom test in the repo (Decision D2) - 5 regression-lock assertions: no maintainer email ever rendered (prop omitted, prop=null), Sign-in link exists with href=/login, supplied email renders when prop is set, no "Guest" placeholder (locks A1 copy choice) - Mocks next/link, next/router (prefetch, replace, events, query), and theme-context.useTheme for jsdom safety under Next 16 package.json + package-lock.json: - Add jsdom@^29 and @testing-library/react@^16 to devDependencies - @testing-library/dom@^10 added explicitly (peer auto-install skipped it under npm 11; brief anticipated this fallback) vitest.config.js (deviation from brief — see PR description): - Add esbuild { loader: 'jsx', jsx: 'automatic' } so vitest can parse JSX in .js files. Required to import any React component written in the repo's Next.js pages-router .js convention (AGENTS.md Gotcha #9). The brief said "no change" to this file, but JSX-in-.js parsing is a hard prerequisite for the new test to import components/Layout.js — the alternatives (rename test to .test.jsx; rewrite test in React.createElement) either break the test glob or still hit the same Layout.js parse failure. Other tests are unaffected (they import non-JSX modules). Smoke output: see PR description. addresses: P0 #7 from .convoys/ship-readiness.md (last P0 ship-blocker) Co-authored-by: Cursor <cursoragent@cursor.com> * feat(pages): pass user explicitly + null-guard leaky page seeds (Brief 2 of fix-layout-default-user) Closes the page-side half of P0 #7 from .convoys/ship-readiness.md. Brief 1 (commit ddf8fd2) handled the Layout-side fix. Per the architect's per-page bucket table (Decision B in .convoys/fix-layout-default-user.md), 7 pages needed code changes; the other 10 of 17 Layout-importing pages already pass `user` correctly. Pass user={user} to Layout (4 pages, 11 call sites): - pages/scanner.js (1 call) - pages/decks.js (3 calls) - pages/deck-builder.js (4 calls) - pages/deck/[id].js (3 calls) (All four still import useAuth from lib/auth-context.js — that's intentional and stays as-is until the single-auth-provider convoy collapses the three parallel auth surfaces.) Replace leaky page-level seed values with useState(null) + null guards (2 pages, R2 mitigation): - pages/profile.js: useState({email: 'me@...', role: 'user', ...}) → useState(null) + ?. on every sync user.* read + early-return guards in getDisplayName/getInitials + conditional render around the "Member since" block so formatDate(undefined) never runs - pages/settings.js: same pattern (single user.email reader guarded) Replace hardcoded const with useAuth from lib/use-auth.js (1 page): - pages/card/[id].js: const user = {email: 'me@...'} → const { user } = useAuth() (called unconditionally at the top of the component; rules-of-hooks safe) Verification: - grep 'me@randallstillwell.com' pages/ → 0 hits - 21/21 vitest tests pass (16 pre-existing + 5 from Brief 1) - npm run lint matches baseline (128 problems pre, 128 post; verified via git stash before/after) - Manual static read-through of every diff; ReadLints clean on the 7 files - Dev-server smoke: /cards anonymous returned HTTP 200 with 0 'me@randallstillwell' matches before the user's shared dev server became unresponsive mid-session (same dev-server-shared-by-user constraint flagged in Brief 1); interactive logged-in smoke is parent/operator gated Flagged-but-deferred (untouched per scope): - 4 pages still import useAuth from lib/auth-context.js → single-auth-provider (queued P1 #9) - components/MobileNavigation.js still receives dead user prop → cleanup-mobile-nav-dead-props (or fold into god-component-split) addresses: P0 #7 from .convoys/ship-readiness.md (last P0 ship-blocker) Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 15:31:37 -04:00
value={user?.email || ''}
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
disabled
className="input-field flex-1 opacity-50 cursor-not-allowed"
/>
<span className="px-3 py-1 text-xs rounded-full bg-green-100 dark:bg-green-900/20 text-green-800 dark:text-green-200">
Verified
</span>
</div>
<p className="text-xs mt-1" style={{ color: 'var(--text-secondary)' }}>
Contact support to change your email address
</p>
</div>
{/* Collection Visibility */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Default List Visibility
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
</label>
<select
value={settings.collection_visibility}
onChange={(e) => handleSettingChange('collection_visibility', e.target.value)}
className="input-field w-full"
>
<option value="private">Private</option>
<option value="public">Public</option>
<option value="unlisted">Unlisted</option>
</select>
<p className="text-xs mt-1" style={{ color: 'var(--text-secondary)' }}>
Controls who can see your new lists by default
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
</p>
</div>
{/* Preferred Currency */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Preferred Currency
</label>
<select
value={settings.preferred_currency}
onChange={(e) => handleSettingChange('preferred_currency', e.target.value)}
className="input-field w-full"
>
{currencyOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
<p className="text-xs mt-1" style={{ color: 'var(--text-secondary)' }}>
Currency used for displaying card values
</p>
</div>
</div>
</div>
)}
{/* Security Settings */}
{activeSection === 'security' && (
<div>
<h2 className="text-2xl font-bold mb-6" style={{ color: 'var(--text-primary)' }}>
Security Settings
</h2>
<div className="space-y-8">
{/* Change Password */}
<div>
<h3 className="text-lg font-semibold mb-4" style={{ color: 'var(--text-primary)' }}>
Change Password
</h3>
<form onSubmit={handlePasswordChange} className="space-y-4">
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Current Password
</label>
<input
type="password"
value={passwordForm.current_password}
onChange={(e) => setPasswordForm(prev => ({ ...prev, current_password: e.target.value }))}
className="input-field w-full"
required
/>
</div>
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
New Password
</label>
<input
type="password"
value={passwordForm.new_password}
onChange={(e) => setPasswordForm(prev => ({ ...prev, new_password: e.target.value }))}
className="input-field w-full"
minLength={8}
required
/>
</div>
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Confirm New Password
</label>
<input
type="password"
value={passwordForm.confirm_password}
onChange={(e) => setPasswordForm(prev => ({ ...prev, confirm_password: e.target.value }))}
className="input-field w-full"
minLength={8}
required
/>
</div>
<button
type="submit"
disabled={changingPassword}
className="px-6 py-2 rounded-xl font-medium transition-all duration-200 hover:shadow-md"
style={{
backgroundColor: 'var(--accent-ember)',
color: 'white'
}}
>
{changingPassword ? 'Changing Password...' : 'Change Password'}
</button>
</form>
</div>
{/* Two-Factor Authentication */}
<div>
<h3 className="text-lg font-semibold mb-4" style={{ color: 'var(--text-primary)' }}>
Two-Factor Authentication
</h3>
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
<div className="glass-panel flex items-center justify-between p-4 rounded-xl">
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
<div>
<p className="font-medium" style={{ color: 'var(--text-primary)' }}>
Enable 2FA
</p>
<p className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Add an extra layer of security to your account
</p>
</div>
<button
onClick={() => handleSettingChange('two_factor_enabled', !settings.two_factor_enabled)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
settings.two_factor_enabled ? 'bg-green-600' : 'bg-gray-300 dark:bg-gray-600'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
settings.two_factor_enabled ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
</div>
{settings.two_factor_enabled && (
<p className="text-sm mt-2 p-3 rounded-lg bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200">
Two-factor authentication is enabled. Use your authenticator app to log in.
</p>
)}
</div>
{/* Danger Zone */}
<div className="border-t pt-8" style={{ borderColor: 'var(--border)' }}>
<h3 className="text-lg font-semibold mb-4 text-red-600 dark:text-red-400">
Danger Zone
</h3>
<div className="p-4 rounded-xl border border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/20">
<div className="flex items-center justify-between">
<div>
<p className="font-medium text-red-800 dark:text-red-200">
Delete Account
</p>
<p className="text-sm text-red-600 dark:text-red-300">
Permanently delete your account and all associated data
</p>
</div>
<button
onClick={handleDeleteAccount}
className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-xl font-medium transition-colors"
>
Delete Account
</button>
</div>
</div>
</div>
</div>
</div>
)}
{/* Preferences */}
{activeSection === 'preferences' && (
<div>
<h2 className="text-2xl font-bold mb-6" style={{ color: 'var(--text-primary)' }}>
Preferences
</h2>
<div className="space-y-6">
{/* Cards Per Page */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Cards Per Page
</label>
<select
value={settings.cards_per_page}
onChange={(e) => handleSettingChange('cards_per_page', parseInt(e.target.value))}
className="input-field w-full"
>
{cardsPerPageOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</div>
{/* Default View */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Default View Mode
</label>
<select
value={settings.default_view}
onChange={(e) => handleSettingChange('default_view', e.target.value)}
className="input-field w-full"
>
{viewOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
</div>
</div>
</div>
)}
{/* Notifications */}
{activeSection === 'notifications' && (
<div>
<h2 className="text-2xl font-bold mb-6" style={{ color: 'var(--text-primary)' }}>
Notification Settings
</h2>
<div className="space-y-6">
{/* Email Notifications */}
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
<div className="glass-panel flex items-center justify-between p-4 rounded-xl">
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
<div>
<p className="font-medium" style={{ color: 'var(--text-primary)' }}>
Email Notifications
</p>
<p className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Receive notifications about your lists and cards
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
</p>
</div>
<button
onClick={() => handleSettingChange('notifications_email', !settings.notifications_email)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
settings.notifications_email ? 'bg-green-600' : 'bg-gray-300 dark:bg-gray-600'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
settings.notifications_email ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
</div>
{/* Marketing Emails */}
feat(design-system): sweep authenticated body-content panels to glass (#97) PR #95/#96 shipped the Liquid Glass foundation (tokens, primitives, gates) plus Layout shell, modals, landing, auth pages, and form CTAs — but body- content panels on authenticated pages (admin Card Editor, admin Card Import, admin Submissions, dashboard, my-cards, settings, scanner panels, card detail price cards, popovers) were still rendering as flat var(--bg-secondary) cards. Result: the admin Tools screen and several core pages looked unchanged after the redesign. This sweep adds a `.glass-panel` / `.glass-panel-strong` utility (<GlassSurface tint=mid/high rim=subtle elevation=ambient/pronounced blur=mid/high> in class form) and applies it across 18 surfaces: * Admin Card Editor view, search panel, form (5 sections), preview * Admin Card Import navigation + 3 body cards + sync panel * Admin Card Submissions list items * Dashboard stat cards + empty-state + grid items (5 surfaces) * My-cards empty-state CTA card * Settings panels (3) * Scanner page settings + grid + queue + bulk toolbar + dialog * Scanner destination picker + camera status banner + disambiguation * Card detail price cards (Current / TCGPlayer / CardKingdom) * Permission indicator tooltips * Collections page header card * Card detail view price cards Also migrates the lingering admin Card Editor "Card Editor / Card Import" nav buttons and the "Save Changes" / "Import Cards" / "Run catalog sync" CTAs to the <Button> primitive (consistent loading + disabled states). Page header bands (full-bleed strips with border-bottom on dashboard, my-cards, cards, collections, community/collections, collection/[id]) are intentionally left solid — they're not card-shaped surfaces and stacking glass-on-glass directly below the already-glass topbar would muddy the hierarchy. Tests: lint clean, vitest 104/104, build green. The visual diff baseline will need refresh because the homepage spec is unaffected (it targets the unauthenticated landing page) but the dashboard/ admin/scanner surfaces will diff if/when we add baselines for them. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 22:28:52 -04:00
<div className="glass-panel flex items-center justify-between p-4 rounded-xl">
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
<div>
<p className="font-medium" style={{ color: 'var(--text-primary)' }}>
Marketing Emails
</p>
<p className="text-sm" style={{ color: 'var(--text-secondary)' }}>
Receive updates about new features and promotions
</p>
</div>
<button
onClick={() => handleSettingChange('notifications_marketing', !settings.notifications_marketing)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
settings.notifications_marketing ? 'bg-green-600' : 'bg-gray-300 dark:bg-gray-600'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
settings.notifications_marketing ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
</div>
</div>
</div>
)}
{/* Display Settings */}
{activeSection === 'display' && (
<div>
<h2 className="text-2xl font-bold mb-6" style={{ color: 'var(--text-primary)' }}>
Display Settings
</h2>
<div className="space-y-6">
{/* Theme */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Theme
</label>
<select
value={settings.theme}
onChange={(e) => handleSettingChange('theme', e.target.value)}
className="input-field w-full"
>
{themeOptions.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
<p className="text-xs mt-1" style={{ color: 'var(--text-secondary)' }}>
System will follow your device&apos;s theme preference
🎯 Build Comprehensive User Profile & Settings System 👤 Profile Page Features: - Complete user profile with avatar, name, username, bio, and email - Avatar upload with file validation (5MB limit, image types only) - Avatar generation functionality for custom avatars - Favorite games selection (MTG, Pokemon, Lorcana) - Collection statistics display (total cards, collections, decks, value) - Profile editing with real-time validation - Member since date and role display ⚙️ Settings Page Features: - Multi-section tabbed interface (Account, Security, Preferences, Notifications, Display) - Account settings: email (read-only), collection visibility, preferred currency - Security settings: password change with validation, 2FA toggle, account deletion - Preferences: cards per page (25/50/100), default view (grid/list) - Notifications: email notifications, marketing emails (toggle switches) - Display settings: theme (light/dark/system), language selection 🗄️ Database Schema Updates: - Added user profile fields: first_name, last_name, username, bio, avatar_url - Added preference fields: favorite_games (JSONB), collection_visibility, preferred_currency, cards_per_page, default_view - Added notification settings: notifications_email, notifications_marketing, two_factor_enabled - Added display settings: theme, language - Created user_settings table for complex settings - Created user_avatars table for avatar management - Added performance indexes and data validation constraints 📡 API Endpoints Created: - GET/PUT /api/user/profile - Profile information management - GET/PUT /api/user/settings - Settings and preferences management - PUT /api/user/password - Secure password change with bcrypt validation - GET /api/user/stats - Collection statistics and analytics 🔒 Security & Validation: - Password change requires current password verification - Username uniqueness validation - Input validation for all enum fields (currency, theme, view mode, etc.) - Proper error handling and user feedback - Authentication required for all user endpoints 🎨 UI/UX Features: - Beautiful fire-themed design matching app branding - Responsive design for mobile and desktop - Loading states and success/error messages - Avatar placeholder with user initials - Tabbed settings interface with icons - Toggle switches for boolean settings - Form validation with helpful error messages ✨ Additional Features: - Collection stats with game/rarity breakdowns - Recent activity tracking - Danger zone for account deletion with double confirmation - Member since display with formatted dates - Currency formatting for collection values - Game icons and themed styling throughout The profile and settings system is now fully functional with comprehensive user management! 👨‍💻✨
2025-07-26 19:05:55 -04:00
</p>
</div>
{/* Language */}
<div>
<label className="block text-sm font-medium mb-2" style={{ color: 'var(--text-primary)' }}>
Language
</label>
<select
value={settings.language}
onChange={(e) => handleSettingChange('language', e.target.value)}
className="input-field w-full"
>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
<option value="de">Deutsch</option>
<option value="ja">日本語</option>
</select>
<p className="text-xs mt-1" style={{ color: 'var(--text-secondary)' }}>
Interface language (coming soon)
</p>
</div>
</div>
</div>
)}
{/* Save Button */}
<div className="flex justify-end pt-8 border-t" style={{ borderColor: 'var(--border)' }}>
<button
onClick={saveSettings}
disabled={saving}
className="px-6 py-3 rounded-xl font-medium transition-all duration-200 hover:shadow-md"
style={{
backgroundColor: 'var(--accent-ember)',
color: 'white'
}}
>
{saving ? 'Saving...' : 'Save Settings'}
</button>
</div>
</div>
</div>
</div>
</div>
</Layout>
);
}