feat: Add optional display name to user profile with corresponding API and UI updates

This commit is contained in:
2025-12-19 18:07:01 +05:30
parent f2f2d1dec7
commit d981ff37fb
4 changed files with 44 additions and 5 deletions

View File

@@ -4,6 +4,7 @@ import { useNavigate, Link } from 'react-router-dom'
interface User {
id: number
username: string
name: string | null
role: string
}
@@ -13,13 +14,21 @@ export function Dashboard() {
const [loading, setLoading] = useState(true)
useEffect(() => {
// First get auth info, then fetch full user profile for name
fetch('/api/auth/me', { credentials: 'include' })
.then(res => res.json())
.then(data => {
if (data.user) {
setUser(data.user)
} else {
if (!data.user) {
navigate('/login')
return null
}
// Fetch full user profile to get name
return fetch(`/api/users/${data.user.id}`, { credentials: 'include' })
.then(res => res.json())
})
.then((profile) => {
if (profile) {
setUser(profile)
}
})
.catch(() => navigate('/login'))
@@ -49,6 +58,9 @@ export function Dashboard() {
localStorage.setItem('theme', newTheme)
}
// Display name or username fallback
const displayName = user.name || user.username
return (
<div style={{ padding: 'var(--space-lg)' }}>
<header style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 'var(--space-xl)' }}>
@@ -70,7 +82,7 @@ export function Dashboard() {
<div className="card" style={{ marginBottom: 'var(--space-lg)' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
<div>
<h3 style={{ marginBottom: 'var(--space-sm)' }}>Welcome, {user.username}</h3>
<h3 style={{ marginBottom: 'var(--space-sm)' }}>Welcome, {displayName}</h3>
<p className="text-secondary text-sm">
Role: <span className="indicator indicator-info">{user.role}</span>
</p>

View File

@@ -10,6 +10,7 @@ interface Diet {
interface UserProfile {
id: number
username: string
name: string | null
role: string
height_cm: number | null
blood_type: string | null
@@ -29,6 +30,7 @@ export function ProfilePage() {
// Form state
const [userId, setUserId] = useState<number | null>(null)
const [username, setUsername] = useState('')
const [name, setName] = useState('')
const [heightCm, setHeightCm] = useState('')
const [bloodType, setBloodType] = useState('')
const [birthdate, setBirthdate] = useState('')
@@ -55,6 +57,7 @@ export function ProfilePage() {
.then((profile: UserProfile) => {
setUserId(profile.id)
setUsername(profile.username)
setName(profile.name || '')
setHeightCm(profile.height_cm?.toString() || '')
setBloodType(profile.blood_type || '')
setBirthdate(profile.birthdate || '')
@@ -82,6 +85,7 @@ export function ProfilePage() {
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({
name: name || null,
height_cm: heightCm ? parseFloat(heightCm) : null,
blood_type: bloodType || null,
birthdate: birthdate || null,
@@ -115,13 +119,24 @@ export function ProfilePage() {
</header>
<form onSubmit={handleSubmit}>
{/* Username (read-only) */}
{/* Account Info */}
<div className="card" style={{ marginBottom: 'var(--space-lg)' }}>
<h3 style={{ marginBottom: 'var(--space-md)' }}>Account</h3>
<div className="form-group">
<label>Username</label>
<input type="text" className="input" value={username} disabled />
</div>
<div className="form-group">
<label htmlFor="name">Display Name</label>
<input
id="name"
type="text"
className="input"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Your full name"
/>
</div>
</div>
{/* Physical Info */}