shinkan-jinkendo/frontend/src/components/admin/FocusAreaNode.jsx

146 lines
5.0 KiB
React
Raw Normal View History

import React from 'react'
function FocusAreaNode({ focusArea, expanded, onToggle, onSelect, selectedId, selectedType }) {
const nodeId = `fa-${focusArea.id}`
const isExpanded = expanded.has(nodeId)
const isSelected = selectedType === 'focus_area' && selectedId === focusArea.id
return (
<div style={{ marginBottom: '12px' }}>
{/* Focus Area Header */}
<div
onClick={() => onSelect(focusArea, 'focus_area')}
style={{
display: 'flex',
alignItems: 'center',
padding: '8px 12px',
borderRadius: '8px',
cursor: 'pointer',
background: isSelected ? 'var(--accent)' : 'transparent',
color: isSelected ? 'white' : 'var(--text1)',
fontWeight: 600
}}
>
<span
onClick={(e) => { e.stopPropagation(); onToggle(nodeId) }}
style={{ marginRight: '8px', cursor: 'pointer', fontSize: '18px' }}
>
{isExpanded ? '▼' : '▶'}
</span>
<span style={{ marginRight: '8px' }}>{focusArea.icon}</span>
<span>{focusArea.name}</span>
</div>
{/* Children: Style Directions + Training Types */}
{isExpanded && (
<div style={{ marginLeft: '28px', marginTop: '8px' }}>
{/* Style Directions Section */}
<div style={{ marginBottom: '12px' }}>
<div style={{ fontSize: '12px', color: 'var(--text3)', marginBottom: '6px', textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span>Stilrichtungen</span>
<button
className="btn"
style={{ fontSize: '11px', padding: '4px 8px' }}
onClick={(e) => {
e.stopPropagation()
onSelect({ _createType: 'style_direction', focus_area_id: focusArea.id, focus_area_name: focusArea.name }, 'create_style_direction')
}}
>
+ Neu
</button>
</div>
{focusArea.style_directions && focusArea.style_directions.map(sd => (
<StyleDirectionNode
key={sd.id}
styleDirection={sd}
onSelect={onSelect}
isSelected={selectedType === 'style_direction' && selectedId === sd.id}
/>
))}
</div>
{/* Training Types Section */}
<div>
<div style={{ fontSize: '12px', color: 'var(--text3)', marginBottom: '6px', textTransform: 'uppercase', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span>Trainingstypen</span>
<button
className="btn"
style={{ fontSize: '11px', padding: '4px 8px' }}
onClick={(e) => {
e.stopPropagation()
onSelect({ _createType: 'training_type', focus_area_id: focusArea.id, focus_area_name: focusArea.name }, 'create_training_type')
}}
>
+ Neu
</button>
</div>
{focusArea.training_types && focusArea.training_types.map(tt => (
<TrainingTypeNode
key={tt.id}
trainingType={tt}
onSelect={onSelect}
isSelected={selectedType === 'training_type' && selectedId === tt.id}
/>
))}
</div>
</div>
)}
</div>
)
}
function StyleDirectionNode({ styleDirection, onSelect, isSelected }) {
return (
<div
onClick={() => onSelect(styleDirection, 'style_direction')}
style={{
padding: '6px 12px',
marginBottom: '4px',
borderRadius: '6px',
cursor: 'pointer',
background: isSelected ? 'var(--accent)' : 'var(--surface2)',
color: isSelected ? 'white' : 'var(--text1)',
fontSize: '14px'
}}
>
{styleDirection.name}
{styleDirection.abbreviation && (
<span style={{ marginLeft: '8px', opacity: 0.7, fontSize: '12px' }}>
({styleDirection.abbreviation})
</span>
)}
{styleDirection.target_groups && styleDirection.target_groups.length > 0 && (
<div style={{ fontSize: '11px', opacity: 0.8, marginTop: '4px' }}>
Zielgruppen: {styleDirection.target_groups.map(tg => tg.name).join(', ')}
</div>
)}
</div>
)
}
function TrainingTypeNode({ trainingType, onSelect, isSelected }) {
return (
<div
onClick={() => onSelect(trainingType, 'training_type')}
style={{
padding: '6px 12px',
marginBottom: '4px',
borderRadius: '6px',
cursor: 'pointer',
background: isSelected ? 'var(--accent)' : 'var(--surface2)',
color: isSelected ? 'white' : 'var(--text1)',
fontSize: '14px'
}}
>
{trainingType.name}
{trainingType.abbreviation && (
<span style={{ marginLeft: '8px', opacity: 0.7, fontSize: '12px' }}>
({trainingType.abbreviation})
</span>
)}
</div>
)
}
export default FocusAreaNode