mitai-jinkendo/frontend/src/pages/ProfileSelect.jsx
Lars Stommer 89b6c0b072
Some checks are pending
Deploy to Raspberry Pi / deploy (push) Waiting to run
Build Test / build-frontend (push) Waiting to run
Build Test / lint-backend (push) Waiting to run
feat: initial commit – Mitai Jinkendo v9a
2026-03-16 13:35:11 +01:00

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>
)
}