- Updated role permissions to allow trainers and users to create clubs and training groups. - Modified database insertion logic to reflect the correct role for trainers during registration. - Enhanced frontend components to display appropriate messages and buttons based on user roles. - Improved user guidance in the Clubs and Training Planning pages, emphasizing the need for clubs and groups before planning training sessions.
705 lines
27 KiB
JavaScript
705 lines
27 KiB
JavaScript
import React, { useState, useEffect } from 'react'
|
|
import api from '../utils/api'
|
|
import { useAuth } from '../context/AuthContext'
|
|
|
|
function ClubsPage() {
|
|
const { user } = useAuth()
|
|
const [activeTab, setActiveTab] = useState('clubs')
|
|
const [clubs, setClubs] = useState([])
|
|
const [divisions, setDivisions] = useState([])
|
|
const [groups, setGroups] = useState([])
|
|
const [loading, setLoading] = useState(true)
|
|
const [showModal, setShowModal] = useState(false)
|
|
const [editing, setEditing] = useState(null)
|
|
const [modalType, setModalType] = useState('club')
|
|
|
|
// Form state
|
|
const [formData, setFormData] = useState({})
|
|
|
|
const isAdmin = user?.role === 'admin' || user?.role === 'superadmin'
|
|
const isTrainer = user?.role === 'trainer' || isAdmin
|
|
const canCreateClub = ['admin', 'superadmin', 'trainer', 'user'].includes(user?.role)
|
|
|
|
useEffect(() => {
|
|
loadData()
|
|
}, [])
|
|
|
|
const loadData = async () => {
|
|
try {
|
|
const [clubsData, divisionsData, groupsData] = await Promise.all([
|
|
api.listClubs(),
|
|
api.listDivisions(),
|
|
api.listTrainingGroups()
|
|
])
|
|
setClubs(clubsData)
|
|
setDivisions(divisionsData)
|
|
setGroups(groupsData)
|
|
} catch (err) {
|
|
console.error('Failed to load data:', err)
|
|
alert('Fehler beim Laden: ' + err.message)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const handleCreate = (type) => {
|
|
setEditing(null)
|
|
setModalType(type)
|
|
|
|
if (type === 'club') {
|
|
setFormData({ name: '', abbreviation: '', description: '', status: 'active' })
|
|
} else if (type === 'division') {
|
|
setFormData({ club_id: '', name: '', focus_area: '' })
|
|
} else if (type === 'group') {
|
|
setFormData({
|
|
club_id: '',
|
|
division_id: '',
|
|
name: '',
|
|
focus: '',
|
|
level: '',
|
|
age_group: '',
|
|
weekday: '',
|
|
time_start: '',
|
|
time_end: '',
|
|
location: '',
|
|
trainer_id: user?.id ?? '',
|
|
co_trainer_ids: [],
|
|
status: 'active'
|
|
})
|
|
}
|
|
|
|
setShowModal(true)
|
|
}
|
|
|
|
const handleEdit = (item, type) => {
|
|
setEditing(item)
|
|
setModalType(type)
|
|
setFormData({ ...item })
|
|
setShowModal(true)
|
|
}
|
|
|
|
const handleDelete = async (item, type) => {
|
|
const confirmMsg = {
|
|
club: `Verein "${item.name}" wirklich löschen? Alle Sparten und Gruppen werden auch gelöscht!`,
|
|
division: `Sparte "${item.name}" wirklich löschen?`,
|
|
group: `Trainingsgruppe "${item.name}" wirklich löschen?`
|
|
}
|
|
|
|
if (!confirm(confirmMsg[type])) return
|
|
|
|
try {
|
|
if (type === 'club') await api.deleteClub(item.id)
|
|
else if (type === 'division') await api.deleteDivision(item.id)
|
|
else if (type === 'group') await api.deleteTrainingGroup(item.id)
|
|
|
|
await loadData()
|
|
} catch (err) {
|
|
alert('Fehler beim Löschen: ' + err.message)
|
|
}
|
|
}
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault()
|
|
|
|
try {
|
|
if (modalType === 'club') {
|
|
if (editing) {
|
|
await api.updateClub(editing.id, formData)
|
|
} else {
|
|
await api.createClub(formData)
|
|
}
|
|
} else if (modalType === 'division') {
|
|
if (editing) {
|
|
await api.updateDivision(editing.id, formData)
|
|
} else {
|
|
await api.createDivision(formData)
|
|
}
|
|
} else if (modalType === 'group') {
|
|
if (editing) {
|
|
await api.updateTrainingGroup(editing.id, formData)
|
|
} else {
|
|
await api.createTrainingGroup(formData)
|
|
}
|
|
}
|
|
|
|
setShowModal(false)
|
|
await loadData()
|
|
} catch (err) {
|
|
alert('Fehler beim Speichern: ' + err.message)
|
|
}
|
|
}
|
|
|
|
const updateFormField = (field, value) => {
|
|
setFormData(prev => ({ ...prev, [field]: value }))
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
|
<div className="spinner"></div>
|
|
<p>Laden...</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div style={{ padding: '2rem' }}>
|
|
<div style={{ maxWidth: '1200px', margin: '0 auto' }}>
|
|
<h1 style={{ marginBottom: '0.75rem' }}>Vereinsverwaltung</h1>
|
|
<p style={{ color: 'var(--text2)', marginBottom: '1.35rem', maxWidth: '46rem', lineHeight: 1.55 }}>
|
|
Für die Trainingsplanung wird mindestens ein <strong>Verein</strong> und eine <strong>Trainingsgruppe</strong> gebraucht.
|
|
Sparten sind optional — typische Eckdaten einer Gruppe (Wochentag, Zeit, Ort) kannst du schrittweise eintragen.
|
|
</p>
|
|
|
|
{/* Tabs */}
|
|
<div style={{
|
|
display: 'flex',
|
|
gap: '0.5rem',
|
|
marginBottom: '1.5rem',
|
|
borderBottom: '2px solid var(--border)'
|
|
}}>
|
|
{['clubs', 'divisions', 'groups'].map(tab => (
|
|
<button
|
|
key={tab}
|
|
onClick={() => setActiveTab(tab)}
|
|
style={{
|
|
padding: '0.75rem 1.5rem',
|
|
background: activeTab === tab ? 'var(--accent)' : 'transparent',
|
|
color: activeTab === tab ? 'white' : 'var(--text1)',
|
|
border: 'none',
|
|
borderRadius: '8px 8px 0 0',
|
|
cursor: 'pointer',
|
|
fontWeight: activeTab === tab ? 'bold' : 'normal'
|
|
}}
|
|
>
|
|
{tab === 'clubs' && 'Vereine'}
|
|
{tab === 'divisions' && 'Sparten'}
|
|
{tab === 'groups' && 'Trainingsgruppen'}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* Clubs Tab */}
|
|
{activeTab === 'clubs' && (
|
|
<>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '1rem' }}>
|
|
<h2>Vereine</h2>
|
|
{canCreateClub && (
|
|
<button className="btn btn-primary" onClick={() => handleCreate('club')}>
|
|
+ Neuer Verein
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
{clubs.length === 0 ? (
|
|
<div className="card">
|
|
<p style={{ color: 'var(--text2)', textAlign: 'center', marginBottom: canCreateClub ? '1rem' : 0 }}>
|
|
Noch kein Verein angelegt.
|
|
{canCreateClub
|
|
? ' Nutze „+ Neuer Verein“ — ein Name reicht zum Start.'
|
|
: ' Bitte einen Administrator oder Support um Anlage.'}
|
|
</p>
|
|
{canCreateClub && (
|
|
<p style={{ color: 'var(--text2)', textAlign: 'center', fontSize: '0.9rem' }}>
|
|
Danach im Tab Trainingsgruppen eine Gruppe diesem Verein zuordnen; Details sind optional.
|
|
</p>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div style={{ display: 'grid', gap: '1rem' }}>
|
|
{clubs.map(club => (
|
|
<div key={club.id} className="card">
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
|
|
<div style={{ flex: 1 }}>
|
|
<h3 style={{ marginBottom: '0.5rem' }}>
|
|
{club.name}
|
|
{club.abbreviation && (
|
|
<span style={{ color: 'var(--text2)', fontSize: '0.875rem', marginLeft: '0.5rem' }}>
|
|
({club.abbreviation})
|
|
</span>
|
|
)}
|
|
</h3>
|
|
{club.description && (
|
|
<p style={{ color: 'var(--text2)', fontSize: '0.875rem' }}>
|
|
{club.description}
|
|
</p>
|
|
)}
|
|
<span style={{
|
|
display: 'inline-block',
|
|
marginTop: '0.5rem',
|
|
fontSize: '0.75rem',
|
|
padding: '0.25rem 0.5rem',
|
|
borderRadius: '4px',
|
|
background: club.status === 'active' ? '#2ea44f' : 'var(--surface2)',
|
|
color: club.status === 'active' ? 'white' : 'var(--text2)'
|
|
}}>
|
|
{club.status}
|
|
</span>
|
|
</div>
|
|
{isAdmin && (
|
|
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
|
<button
|
|
className="btn btn-secondary"
|
|
onClick={() => handleEdit(club, 'club')}
|
|
>
|
|
Bearbeiten
|
|
</button>
|
|
<button
|
|
className="btn"
|
|
style={{
|
|
background: 'var(--danger)',
|
|
color: 'white',
|
|
border: 'none'
|
|
}}
|
|
onClick={() => handleDelete(club, 'club')}
|
|
>
|
|
Löschen
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{/* Divisions Tab */}
|
|
{activeTab === 'divisions' && (
|
|
<>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '1rem' }}>
|
|
<h2>Sparten</h2>
|
|
{isAdmin && (
|
|
<button className="btn btn-primary" onClick={() => handleCreate('division')}>
|
|
+ Neue Sparte
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
{divisions.length === 0 ? (
|
|
<div className="card">
|
|
<p style={{ color: 'var(--text2)', textAlign: 'center' }}>
|
|
Keine Sparten gefunden
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<div style={{ display: 'grid', gap: '1rem' }}>
|
|
{divisions.map(division => (
|
|
<div key={division.id} className="card">
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
|
|
<div style={{ flex: 1 }}>
|
|
<h3 style={{ marginBottom: '0.5rem' }}>{division.name}</h3>
|
|
<p style={{ color: 'var(--text2)', fontSize: '0.875rem' }}>
|
|
Verein: {division.club_name}
|
|
</p>
|
|
{division.focus_area && (
|
|
<span style={{
|
|
display: 'inline-block',
|
|
marginTop: '0.5rem',
|
|
fontSize: '0.75rem',
|
|
padding: '0.25rem 0.5rem',
|
|
borderRadius: '4px',
|
|
background: 'var(--surface2)',
|
|
color: 'var(--text2)'
|
|
}}>
|
|
{division.focus_area}
|
|
</span>
|
|
)}
|
|
</div>
|
|
{isAdmin && (
|
|
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
|
<button
|
|
className="btn btn-secondary"
|
|
onClick={() => handleEdit(division, 'division')}
|
|
>
|
|
Bearbeiten
|
|
</button>
|
|
<button
|
|
className="btn"
|
|
style={{
|
|
background: 'var(--danger)',
|
|
color: 'white',
|
|
border: 'none'
|
|
}}
|
|
onClick={() => handleDelete(division, 'division')}
|
|
>
|
|
Löschen
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{/* Training Groups Tab */}
|
|
{activeTab === 'groups' && (
|
|
<>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '1rem' }}>
|
|
<h2>Trainingsgruppen</h2>
|
|
{canCreateClub && (
|
|
<button className="btn btn-primary" onClick={() => handleCreate('group')}>
|
|
+ Neue Gruppe
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
{groups.length === 0 ? (
|
|
<div className="card">
|
|
<p style={{ color: 'var(--text2)', textAlign: 'center' }}>
|
|
Keine Trainingsgruppen gefunden
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<div style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',
|
|
gap: '1rem'
|
|
}}>
|
|
{groups.map(group => (
|
|
<div key={group.id} className="card">
|
|
<h3 style={{ marginBottom: '0.5rem' }}>{group.name}</h3>
|
|
<p style={{ color: 'var(--text2)', fontSize: '0.875rem', marginBottom: '0.5rem' }}>
|
|
{group.club_name}
|
|
{group.division_name && ` · ${group.division_name}`}
|
|
</p>
|
|
|
|
<div style={{ fontSize: '0.875rem', color: 'var(--text2)', marginBottom: '1rem' }}>
|
|
{group.weekday && group.time_start && (
|
|
<div>📅 {group.weekday}, {group.time_start.slice(0,5)} - {group.time_end?.slice(0,5)}</div>
|
|
)}
|
|
{group.location && <div>📍 {group.location}</div>}
|
|
{group.trainer_name && <div>👤 {group.trainer_name}</div>}
|
|
{group.level && <div>⭐ {group.level}</div>}
|
|
{group.age_group && <div>👶 {group.age_group}</div>}
|
|
</div>
|
|
|
|
{(isAdmin || group.trainer_id === user?.id) && (
|
|
<div style={{ display: 'flex', gap: '0.5rem', marginTop: 'auto' }}>
|
|
<button
|
|
className="btn btn-secondary"
|
|
style={{ flex: 1 }}
|
|
onClick={() => handleEdit(group, 'group')}
|
|
>
|
|
Bearbeiten
|
|
</button>
|
|
{isAdmin && (
|
|
<button
|
|
className="btn"
|
|
style={{
|
|
background: 'var(--danger)',
|
|
color: 'white',
|
|
border: 'none'
|
|
}}
|
|
onClick={() => handleDelete(group, 'group')}
|
|
>
|
|
Löschen
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{/* Modal */}
|
|
{showModal && (
|
|
<div style={{
|
|
position: 'fixed',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
background: 'rgba(0,0,0,0.5)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
zIndex: 1000,
|
|
padding: '1rem'
|
|
}}>
|
|
<div style={{
|
|
background: 'var(--surface)',
|
|
borderRadius: '12px',
|
|
padding: '2rem',
|
|
maxWidth: '600px',
|
|
width: '100%',
|
|
maxHeight: '90vh',
|
|
overflowY: 'auto'
|
|
}}>
|
|
<h2 style={{ marginBottom: '1.5rem' }}>
|
|
{editing
|
|
? (modalType === 'club' ? 'Verein bearbeiten' : modalType === 'division' ? 'Sparte bearbeiten' : 'Gruppe bearbeiten')
|
|
: (modalType === 'club' ? 'Neuer Verein' : modalType === 'division' ? 'Neue Sparte' : 'Neue Gruppe')
|
|
}
|
|
</h2>
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
{/* Club Form */}
|
|
{modalType === 'club' && (
|
|
<>
|
|
<div className="form-row">
|
|
<label className="form-label">Name *</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.name || ''}
|
|
onChange={(e) => updateFormField('name', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Kürzel</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.abbreviation || ''}
|
|
onChange={(e) => updateFormField('abbreviation', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Beschreibung</label>
|
|
<textarea
|
|
className="form-input"
|
|
rows={3}
|
|
value={formData.description || ''}
|
|
onChange={(e) => updateFormField('description', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Status</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.status || 'active'}
|
|
onChange={(e) => updateFormField('status', e.target.value)}
|
|
>
|
|
<option value="active">Aktiv</option>
|
|
<option value="inactive">Inaktiv</option>
|
|
</select>
|
|
</div>
|
|
</>
|
|
)}
|
|
|
|
{/* Division Form */}
|
|
{modalType === 'division' && (
|
|
<>
|
|
<div className="form-row">
|
|
<label className="form-label">Verein *</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.club_id || ''}
|
|
onChange={(e) => updateFormField('club_id', parseInt(e.target.value))}
|
|
required
|
|
disabled={editing}
|
|
>
|
|
<option value="">Bitte wählen</option>
|
|
{clubs.map(club => (
|
|
<option key={club.id} value={club.id}>{club.name}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Name *</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.name || ''}
|
|
onChange={(e) => updateFormField('name', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Fokusbereich</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.focus_area || ''}
|
|
onChange={(e) => updateFormField('focus_area', e.target.value)}
|
|
>
|
|
<option value="">Bitte wählen</option>
|
|
<option value="karate">Karate</option>
|
|
<option value="selbstverteidigung">Selbstverteidigung</option>
|
|
<option value="gewaltschutz">Gewaltschutz</option>
|
|
</select>
|
|
</div>
|
|
</>
|
|
)}
|
|
|
|
{/* Group Form */}
|
|
{modalType === 'group' && (
|
|
<>
|
|
<div className="form-row">
|
|
<label className="form-label">Verein *</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.club_id || ''}
|
|
onChange={(e) => updateFormField('club_id', parseInt(e.target.value))}
|
|
required
|
|
disabled={editing}
|
|
>
|
|
<option value="">Bitte wählen</option>
|
|
{clubs.map(club => (
|
|
<option key={club.id} value={club.id}>{club.name}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Sparte (optional)</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.division_id || ''}
|
|
onChange={(e) => updateFormField('division_id', e.target.value ? parseInt(e.target.value) : null)}
|
|
>
|
|
<option value="">Keine Sparte</option>
|
|
{divisions.filter(d => d.club_id === formData.club_id).map(div => (
|
|
<option key={div.id} value={div.id}>{div.name}</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Name *</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.name || ''}
|
|
onChange={(e) => updateFormField('name', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem' }}>
|
|
<div className="form-row">
|
|
<label className="form-label">Level</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.level || ''}
|
|
onChange={(e) => updateFormField('level', e.target.value)}
|
|
placeholder="z.B. Anfänger, Fortgeschritten"
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Altersgruppe</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.age_group || ''}
|
|
onChange={(e) => updateFormField('age_group', e.target.value)}
|
|
placeholder="z.B. Kinder, Erwachsene"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '1rem' }}>
|
|
<div className="form-row">
|
|
<label className="form-label">Wochentag</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.weekday || ''}
|
|
onChange={(e) => updateFormField('weekday', e.target.value)}
|
|
>
|
|
<option value="">-</option>
|
|
<option value="Montag">Montag</option>
|
|
<option value="Dienstag">Dienstag</option>
|
|
<option value="Mittwoch">Mittwoch</option>
|
|
<option value="Donnerstag">Donnerstag</option>
|
|
<option value="Freitag">Freitag</option>
|
|
<option value="Samstag">Samstag</option>
|
|
<option value="Sonntag">Sonntag</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Von</label>
|
|
<input
|
|
type="time"
|
|
className="form-input"
|
|
value={formData.time_start || ''}
|
|
onChange={(e) => updateFormField('time_start', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Bis</label>
|
|
<input
|
|
type="time"
|
|
className="form-input"
|
|
value={formData.time_end || ''}
|
|
onChange={(e) => updateFormField('time_end', e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Ort</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.location || ''}
|
|
onChange={(e) => updateFormField('location', e.target.value)}
|
|
placeholder="z.B. Sporthalle Musterstadt"
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Fokus</label>
|
|
<input
|
|
type="text"
|
|
className="form-input"
|
|
value={formData.focus || ''}
|
|
onChange={(e) => updateFormField('focus', e.target.value)}
|
|
placeholder="z.B. Kata, Kumite"
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-row">
|
|
<label className="form-label">Status</label>
|
|
<select
|
|
className="form-input"
|
|
value={formData.status || 'active'}
|
|
onChange={(e) => updateFormField('status', e.target.value)}
|
|
>
|
|
<option value="active">Aktiv</option>
|
|
<option value="inactive">Inaktiv</option>
|
|
</select>
|
|
</div>
|
|
</>
|
|
)}
|
|
|
|
{/* Buttons */}
|
|
<div style={{ display: 'flex', gap: '0.5rem', marginTop: '1.5rem' }}>
|
|
<button type="submit" className="btn btn-primary" style={{ flex: 1 }}>
|
|
{editing ? 'Speichern' : 'Erstellen'}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="btn btn-secondary"
|
|
onClick={() => setShowModal(false)}
|
|
>
|
|
Abbrechen
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default ClubsPage
|