fix: move TrainingTypeDistribution to History + improve admin form UX
UX improvements based on user feedback: 1. Move TrainingTypeDistribution from ActivityPage to History page - ActivityPage is for data entry, not visualization - History (Verlauf) shows personal development/progress - Chart now respects period selector (7/30/90/365 days) 2. Improve AdminTrainingTypesPage form styling - All input fields now full width (100%) - Labels changed from inline to headings above fields - Textareas increased from 2 to 4 rows - Added resize: vertical for textareas - Increased gap between fields from 12px to 16px - Follows style guide conventions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
eecc00e824
commit
967d92025c
|
|
@ -5,7 +5,6 @@ import { api } from '../utils/api'
|
|||
import UsageBadge from '../components/UsageBadge'
|
||||
import TrainingTypeSelect from '../components/TrainingTypeSelect'
|
||||
import BulkCategorize from '../components/BulkCategorize'
|
||||
import TrainingTypeDistribution from '../components/TrainingTypeDistribution'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/de'
|
||||
dayjs.locale('de')
|
||||
|
|
@ -303,11 +302,6 @@ export default function ActivityPage() {
|
|||
|
||||
{tab==='stats' && stats && (
|
||||
<div>
|
||||
<div className="card section-gap">
|
||||
<div className="card-title">🏋️ Trainingstyp-Verteilung (30 Tage)</div>
|
||||
<TrainingTypeDistribution days={30} />
|
||||
</div>
|
||||
|
||||
{chartData.length>=2 && (
|
||||
<div className="card section-gap">
|
||||
<div className="card-title">Aktive Kalorien pro Tag</div>
|
||||
|
|
|
|||
|
|
@ -169,13 +169,14 @@ export default function AdminTrainingTypesPage() {
|
|||
{editingId === 'new' ? '➕ Neuer Trainingstyp' : '✏️ Trainingstyp bearbeiten'}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
|
||||
<div>
|
||||
<label className="form-label">Kategorie *</label>
|
||||
<div className="form-label">Kategorie *</div>
|
||||
<select
|
||||
className="form-input"
|
||||
value={formData.category}
|
||||
onChange={e => setFormData({ ...formData, category: e.target.value })}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{Object.keys(categories).map(cat => (
|
||||
<option key={cat} value={cat}>
|
||||
|
|
@ -186,58 +187,61 @@ export default function AdminTrainingTypesPage() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="form-label">Subkategorie</label>
|
||||
<div className="form-label">Subkategorie</div>
|
||||
<input
|
||||
className="form-input"
|
||||
value={formData.subcategory}
|
||||
onChange={e => setFormData({ ...formData, subcategory: e.target.value })}
|
||||
placeholder="z.B. running, hypertrophy, meditation"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
<div style={{ fontSize: 11, color: 'var(--text3)', marginTop: 4 }}>
|
||||
Kleingeschrieben, ohne Leerzeichen, eindeutig
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
|
||||
<div>
|
||||
<label className="form-label">Name (Deutsch) *</label>
|
||||
<input
|
||||
className="form-input"
|
||||
value={formData.name_de}
|
||||
onChange={e => setFormData({ ...formData, name_de: e.target.value })}
|
||||
placeholder="z.B. Laufen"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="form-label">Name (English) *</label>
|
||||
<input
|
||||
className="form-input"
|
||||
value={formData.name_en}
|
||||
onChange={e => setFormData({ ...formData, name_en: e.target.value })}
|
||||
placeholder="e.g. Running"
|
||||
/>
|
||||
</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>
|
||||
<label className="form-label">Icon (Emoji)</label>
|
||||
<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>
|
||||
<label className="form-label">Sortierung</label>
|
||||
<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 style={{ fontSize: 11, color: 'var(--text3)', marginTop: 4 }}>
|
||||
Niedrigere Zahlen werden zuerst angezeigt
|
||||
|
|
@ -245,24 +249,26 @@ export default function AdminTrainingTypesPage() {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<label className="form-label">Beschreibung (Deutsch)</label>
|
||||
<div className="form-label">Beschreibung (Deutsch)</div>
|
||||
<textarea
|
||||
className="form-input"
|
||||
value={formData.description_de}
|
||||
onChange={e => setFormData({ ...formData, description_de: e.target.value })}
|
||||
placeholder="Optional: Beschreibung für KI-Analyse"
|
||||
rows={2}
|
||||
rows={4}
|
||||
style={{ width: '100%', resize: 'vertical' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="form-label">Beschreibung (English)</label>
|
||||
<div className="form-label">Beschreibung (English)</div>
|
||||
<textarea
|
||||
className="form-input"
|
||||
value={formData.description_en}
|
||||
onChange={e => setFormData({ ...formData, description_en: e.target.value })}
|
||||
placeholder="Optional: Description for AI analysis"
|
||||
rows={2}
|
||||
rows={4}
|
||||
style={{ width: '100%', resize: 'vertical' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { api } from '../utils/api'
|
|||
import { getBfCategory } from '../utils/calc'
|
||||
import { getInterpretation, getStatusColor, getStatusBg } from '../utils/interpret'
|
||||
import Markdown from '../utils/Markdown'
|
||||
import TrainingTypeDistribution from '../components/TrainingTypeDistribution'
|
||||
import dayjs from 'dayjs'
|
||||
import 'dayjs/locale/de'
|
||||
dayjs.locale('de')
|
||||
|
|
@ -653,6 +654,10 @@ function ActivitySection({ activities, insights, onRequest, loadingSlug, filterA
|
|||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="card" style={{marginBottom:12}}>
|
||||
<div style={{fontSize:12,fontWeight:600,color:'var(--text3)',marginBottom:8}}>Trainingstyp-Verteilung</div>
|
||||
<TrainingTypeDistribution days={period === 9999 ? 365 : period} />
|
||||
</div>
|
||||
<div style={{marginBottom:12}}>
|
||||
<div style={{fontSize:12,fontWeight:600,color:'var(--text3)',marginBottom:8}}>BEWERTUNG</div>
|
||||
{actRules.map((item,i)=><RuleCard key={i} item={item}/>)}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user