125 lines
5.6 KiB
JavaScript
125 lines
5.6 KiB
JavaScript
import { useState } from 'react'
|
|
import { Plus, Check } from 'lucide-react'
|
|
import { useProfile } from '../context/ProfileContext'
|
|
import { api } from '../utils/api'
|
|
|
|
const COLORS = ['#1D9E75','#378ADD','#D85A30','#EF9F27','#7F77DD','#D4537E','#639922','#888780']
|
|
const AVATARS = ['👤','👦','👧','👨','👩','🧔','👴','👵','🧒','🧑']
|
|
|
|
function Avatar({ profile, size=48, onClick, selected }) {
|
|
const initials = profile.name.split(' ').map(n=>n[0]).join('').toUpperCase().slice(0,2)
|
|
return (
|
|
<div onClick={onClick} style={{
|
|
width:size, height:size, borderRadius:'50%',
|
|
background: profile.avatar_color || '#1D9E75',
|
|
display:'flex', alignItems:'center', justifyContent:'center',
|
|
fontSize: size*0.38, fontWeight:700, color:'white', cursor:onClick?'pointer':'default',
|
|
border: selected ? '3px solid white' : '3px solid transparent',
|
|
boxShadow: selected ? `0 0 0 3px ${profile.avatar_color}` : 'none',
|
|
transition:'all 0.15s', flexShrink:0,
|
|
}}>
|
|
{initials}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export { Avatar }
|
|
|
|
export default function ProfileSelect() {
|
|
const { profiles, setActiveProfile, refreshProfiles } = useProfile()
|
|
const [creating, setCreating] = useState(false)
|
|
const [newName, setNewName] = useState('')
|
|
const [newColor, setNewColor] = useState(COLORS[0])
|
|
const [saving, setSaving] = useState(false)
|
|
|
|
const handleCreate = async () => {
|
|
if (!newName.trim()) return
|
|
setSaving(true)
|
|
try {
|
|
const p = await api.createProfile({ name: newName.trim(), avatar_color: newColor })
|
|
// Refresh profile list first, then set active
|
|
await refreshProfiles()
|
|
setActiveProfile(p)
|
|
setCreating(false)
|
|
setNewName('')
|
|
} catch(e) {
|
|
console.error('Create profile error:', e)
|
|
} finally { setSaving(false) }
|
|
}
|
|
|
|
return (
|
|
<div style={{
|
|
minHeight:'100vh', display:'flex', flexDirection:'column',
|
|
alignItems:'center', justifyContent:'center',
|
|
background:'var(--bg)', padding:24,
|
|
}}>
|
|
<div style={{marginBottom:24,textAlign:'center'}}>
|
|
<div style={{fontSize:32,fontWeight:800,color:'var(--accent)',letterSpacing:'-0.5px'}}>BodyTrack</div>
|
|
<div style={{fontSize:15,color:'var(--text3)',marginTop:4}}>Wer bist du?</div>
|
|
</div>
|
|
|
|
<div style={{width:'100%',maxWidth:360}}>
|
|
{profiles.map(p => (
|
|
<div key={p.id} onClick={()=>setActiveProfile(p)}
|
|
style={{display:'flex',alignItems:'center',gap:14,padding:'14px 16px',
|
|
background:'var(--surface)',borderRadius:14,marginBottom:10,cursor:'pointer',
|
|
border:'1.5px solid var(--border)',transition:'all 0.15s'}}
|
|
onMouseEnter={e=>e.currentTarget.style.borderColor='var(--accent)'}
|
|
onMouseLeave={e=>e.currentTarget.style.borderColor='var(--border)'}>
|
|
<Avatar profile={p} size={52}/>
|
|
<div style={{flex:1}}>
|
|
<div style={{fontWeight:600,fontSize:16}}>{p.name}</div>
|
|
<div style={{fontSize:12,color:'var(--text3)',marginTop:2}}>
|
|
{p.sex==='m'?'Männlich':'Weiblich'}{p.height?` · ${p.height} cm`:''}
|
|
{p.goal_weight?` · Ziel: ${p.goal_weight} kg`:''}
|
|
</div>
|
|
</div>
|
|
<div style={{fontSize:20,color:'var(--text3)'}}>→</div>
|
|
</div>
|
|
))}
|
|
|
|
{!creating ? (
|
|
<button onClick={()=>setCreating(true)}
|
|
style={{width:'100%',padding:'13px 16px',borderRadius:14,
|
|
border:'1.5px dashed var(--border2)',background:'transparent',
|
|
color:'var(--text3)',fontSize:14,cursor:'pointer',fontFamily:'var(--font)',
|
|
display:'flex',alignItems:'center',justifyContent:'center',gap:8}}>
|
|
<Plus size={16}/> Neues Profil erstellen
|
|
</button>
|
|
) : (
|
|
<div style={{background:'var(--surface)',borderRadius:14,padding:16,border:'1.5px solid var(--accent)'}}>
|
|
<div style={{fontWeight:600,fontSize:14,marginBottom:12}}>Neues Profil</div>
|
|
<input
|
|
type="text" placeholder="Name eingeben"
|
|
value={newName} onChange={e=>setNewName(e.target.value)}
|
|
onKeyDown={e=>e.key==='Enter'&&handleCreate()}
|
|
style={{width:'100%',padding:'10px 12px',borderRadius:8,fontSize:15,fontWeight:500,
|
|
border:'1.5px solid var(--border2)',background:'var(--surface2)',
|
|
color:'var(--text1)',fontFamily:'var(--font)',boxSizing:'border-box',marginBottom:12}}
|
|
autoFocus/>
|
|
<div style={{marginBottom:12}}>
|
|
<div style={{fontSize:12,color:'var(--text3)',marginBottom:8}}>Farbe wählen</div>
|
|
<div style={{display:'flex',gap:8,flexWrap:'wrap'}}>
|
|
{COLORS.map(c=>(
|
|
<div key={c} onClick={()=>setNewColor(c)}
|
|
style={{width:32,height:32,borderRadius:'50%',background:c,cursor:'pointer',
|
|
border:`3px solid ${newColor===c?'white':'transparent'}`,
|
|
boxShadow:newColor===c?`0 0 0 2px ${c}`:'none',transition:'all 0.1s'}}/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div style={{display:'flex',gap:8}}>
|
|
<button onClick={handleCreate} disabled={saving||!newName.trim()}
|
|
className="btn btn-primary" style={{flex:1}}>
|
|
{saving?<div className="spinner" style={{width:14,height:14}}/>:<><Check size={14}/> Erstellen</>}
|
|
</button>
|
|
<button onClick={()=>{setCreating(false);setNewName('')}}
|
|
className="btn btn-secondary" style={{flex:1}}>Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|