fix: restore inline editing for training type profiles
- ProfileBuilder now renders inline below training type row - Type editor form also inline (not at top of page) - Both forms appear at item position with marginTop: 8 - User feedback: 'Die Position bleibt die ganze Zeit gleich!' Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6fa15f7f57
commit
41c7084159
|
|
@ -189,20 +189,8 @@ export default function AdminTrainingTypesPage() {
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Profile Builder */}
|
{/* Edit form (only for new type creation, at top) */}
|
||||||
{editingProfileId && (
|
{editingId === 'new' && formData && (
|
||||||
<div style={{ marginBottom: 16 }}>
|
|
||||||
<ProfileBuilder
|
|
||||||
trainingType={types.find(t => t.id === editingProfileId)}
|
|
||||||
parameters={parameters}
|
|
||||||
onSave={handleSaveProfile}
|
|
||||||
onCancel={cancelEditProfile}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Edit form */}
|
|
||||||
{editingId && formData && (
|
|
||||||
<div className="card" style={{ padding: 16, marginBottom: 16 }}>
|
<div className="card" style={{ padding: 16, marginBottom: 16 }}>
|
||||||
<div style={{ fontWeight: 600, marginBottom: 12 }}>
|
<div style={{ fontWeight: 600, marginBottom: 12 }}>
|
||||||
{editingId === 'new' ? '➕ Neuer Trainingstyp' : '✏️ Trainingstyp bearbeiten'}
|
{editingId === 'new' ? '➕ Neuer Trainingstyp' : '✏️ Trainingstyp bearbeiten'}
|
||||||
|
|
@ -360,79 +348,182 @@ export default function AdminTrainingTypesPage() {
|
||||||
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
{catTypes.sort((a, b) => a.sort_order - b.sort_order).map(type => (
|
{catTypes.sort((a, b) => a.sort_order - b.sort_order).map(type => (
|
||||||
<div
|
<div key={type.id}>
|
||||||
key={type.id}
|
{/* Type Row */}
|
||||||
style={{
|
<div
|
||||||
display: 'flex',
|
style={{
|
||||||
alignItems: 'center',
|
display: 'flex',
|
||||||
gap: 8,
|
alignItems: 'center',
|
||||||
padding: 8,
|
gap: 8,
|
||||||
background: 'var(--surface)',
|
padding: 8,
|
||||||
borderRadius: 6
|
background: 'var(--surface)',
|
||||||
}}
|
borderRadius: 6
|
||||||
>
|
}}
|
||||||
<div style={{ fontSize: 18 }}>{type.icon}</div>
|
>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ fontSize: 18 }}>{type.icon}</div>
|
||||||
<div style={{ fontSize: 13, fontWeight: 500 }}>
|
<div style={{ flex: 1 }}>
|
||||||
{type.name_de} <span style={{ color: 'var(--text3)' }}>/ {type.name_en}</span>
|
<div style={{ fontSize: 13, fontWeight: 500 }}>
|
||||||
{type.profile && (
|
{type.name_de} <span style={{ color: 'var(--text3)' }}>/ {type.name_en}</span>
|
||||||
<span style={{
|
{type.profile && (
|
||||||
marginLeft: 8,
|
<span style={{
|
||||||
padding: '2px 6px',
|
marginLeft: 8,
|
||||||
background: 'var(--accent)',
|
padding: '2px 6px',
|
||||||
color: 'white',
|
background: 'var(--accent)',
|
||||||
borderRadius: 4,
|
color: 'white',
|
||||||
fontSize: 10
|
borderRadius: 4,
|
||||||
}}>
|
fontSize: 10
|
||||||
✓ Profil
|
}}>
|
||||||
</span>
|
✓ Profil
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{type.subcategory && (
|
||||||
|
<div style={{ fontSize: 11, color: 'var(--text3)' }}>
|
||||||
|
Subkategorie: {type.subcategory}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{type.subcategory && (
|
<button
|
||||||
<div style={{ fontSize: 11, color: 'var(--text3)' }}>
|
onClick={() => startEditProfile(type.id)}
|
||||||
Subkategorie: {type.subcategory}
|
style={{
|
||||||
</div>
|
background: 'none',
|
||||||
)}
|
border: 'none',
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: 6,
|
||||||
|
color: 'var(--accent)'
|
||||||
|
}}
|
||||||
|
title="Profil konfigurieren"
|
||||||
|
>
|
||||||
|
<Settings size={16} />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => startEdit(type)}
|
||||||
|
style={{
|
||||||
|
background: 'none',
|
||||||
|
border: 'none',
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: 6,
|
||||||
|
color: 'var(--accent)'
|
||||||
|
}}
|
||||||
|
title="Bearbeiten"
|
||||||
|
>
|
||||||
|
<Pencil size={16} />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => handleDelete(type.id, type.name_de)}
|
||||||
|
style={{
|
||||||
|
background: 'none',
|
||||||
|
border: 'none',
|
||||||
|
cursor: 'pointer',
|
||||||
|
padding: 6,
|
||||||
|
color: '#D85A30'
|
||||||
|
}}
|
||||||
|
title="Löschen"
|
||||||
|
>
|
||||||
|
<Trash2 size={16} />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
onClick={() => startEditProfile(type.id)}
|
{/* Inline Profile Builder */}
|
||||||
style={{
|
{editingProfileId === type.id && (
|
||||||
background: 'none',
|
<div style={{ marginTop: 8 }}>
|
||||||
border: 'none',
|
<ProfileBuilder
|
||||||
cursor: 'pointer',
|
trainingType={type}
|
||||||
padding: 6,
|
parameters={parameters}
|
||||||
color: 'var(--accent)'
|
onSave={handleSaveProfile}
|
||||||
}}
|
onCancel={cancelEditProfile}
|
||||||
title="Profil konfigurieren"
|
/>
|
||||||
>
|
</div>
|
||||||
<Settings size={16} />
|
)}
|
||||||
</button>
|
|
||||||
<button
|
{/* Inline Type Editor */}
|
||||||
onClick={() => startEdit(type)}
|
{editingId === type.id && formData && (
|
||||||
style={{
|
<div style={{ marginTop: 8, padding: 16, background: 'var(--surface2)', borderRadius: 8 }}>
|
||||||
background: 'none',
|
<div style={{ fontWeight: 600, marginBottom: 12 }}>✏️ Trainingstyp bearbeiten</div>
|
||||||
border: 'none',
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
|
||||||
cursor: 'pointer',
|
<div>
|
||||||
padding: 6,
|
<div className="form-label">Kategorie *</div>
|
||||||
color: 'var(--accent)'
|
<select
|
||||||
}}
|
className="form-input"
|
||||||
title="Bearbeiten"
|
value={formData.category}
|
||||||
>
|
onChange={e => setFormData({ ...formData, category: e.target.value })}
|
||||||
<Pencil size={16} />
|
style={{ width: '100%' }}
|
||||||
</button>
|
>
|
||||||
<button
|
{Object.keys(categories).map(cat => (
|
||||||
onClick={() => handleDelete(type.id, type.name_de)}
|
<option key={cat} value={cat}>
|
||||||
style={{
|
{categories[cat].icon} {categories[cat].name_de}
|
||||||
background: 'none',
|
</option>
|
||||||
border: 'none',
|
))}
|
||||||
cursor: 'pointer',
|
</select>
|
||||||
padding: 6,
|
</div>
|
||||||
color: '#D85A30'
|
|
||||||
}}
|
<div>
|
||||||
title="Löschen"
|
<div className="form-label">Subkategorie</div>
|
||||||
>
|
<input
|
||||||
<Trash2 size={16} />
|
className="form-input"
|
||||||
</button>
|
value={formData.subcategory}
|
||||||
|
onChange={e => setFormData({ ...formData, subcategory: e.target.value })}
|
||||||
|
placeholder="z.B. running, hypertrophy, meditation"
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="form-label">Name (Deutsch) *</div>
|
||||||
|
<input
|
||||||
|
className="form-input"
|
||||||
|
value={formData.name_de}
|
||||||
|
onChange={e => setFormData({ ...formData, name_de: e.target.value })}
|
||||||
|
placeholder="z.B. Laufen"
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="form-label">Name (English) *</div>
|
||||||
|
<input
|
||||||
|
className="form-input"
|
||||||
|
value={formData.name_en}
|
||||||
|
onChange={e => setFormData({ ...formData, name_en: e.target.value })}
|
||||||
|
placeholder="e.g. Running"
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="form-label">Icon (Emoji)</div>
|
||||||
|
<input
|
||||||
|
className="form-input"
|
||||||
|
value={formData.icon}
|
||||||
|
onChange={e => setFormData({ ...formData, icon: e.target.value })}
|
||||||
|
placeholder="🏃"
|
||||||
|
maxLength={10}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="form-label">Sortierung</div>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-input"
|
||||||
|
value={formData.sort_order}
|
||||||
|
onChange={e => setFormData({ ...formData, sort_order: parseInt(e.target.value) })}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', gap: 8 }}>
|
||||||
|
<button onClick={handleSave} disabled={saving} className="btn btn-primary" style={{ flex: 1 }}>
|
||||||
|
{saving ? <><div className="spinner" style={{ width: 14, height: 14 }} /> Speichere...</> : <><Save size={16} /> Speichern</>}
|
||||||
|
</button>
|
||||||
|
<button onClick={cancelEdit} disabled={saving} className="btn btn-secondary" style={{ flex: 1 }}>
|
||||||
|
<X size={16} /> Abbrechen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user