feat: enhance TrainingPlanningPage with new utility functions and state management improvements
All checks were successful
Deploy Development / deploy (push) Successful in 35s
Test Suite / pytest-backend (push) Successful in 6s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 6s
Test Suite / playwright-tests (push) Successful in 23s
All checks were successful
Deploy Development / deploy (push) Successful in 35s
Test Suite / pytest-backend (push) Successful in 6s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 6s
Test Suite / playwright-tests (push) Successful in 23s
- Added utility functions to normalize co-trainer IDs and filter directory entries, improving data handling for training groups. - Updated state management to remove reliance on the user profile for club admin checks, enhancing performance and clarity. - Improved session assignment logic to ensure effective lead trainers are excluded from assistant trainer lists. - Enhanced form field updates to manage session assistant IDs more effectively, streamlining the assignment process.
This commit is contained in:
parent
9dbd3cbd5f
commit
56ea36ea25
|
|
@ -87,6 +87,28 @@ const sessionAssignDefaults = () => ({
|
||||||
session_assistants_inherit: true,
|
session_assistants_inherit: true,
|
||||||
session_assistant_profile_ids: [],
|
session_assistant_profile_ids: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/** Co_trainer_ids aus TrainingGroups (Liste/JSON) → Zahlenliste */
|
||||||
|
function normalizeGroupCoTrainerIds(raw) {
|
||||||
|
if (raw == null) return []
|
||||||
|
const arr = Array.isArray(raw) ? raw : []
|
||||||
|
const out = []
|
||||||
|
for (const x of arr) {
|
||||||
|
const n = Number(x)
|
||||||
|
if (Number.isFinite(n) && n >= 1) out.push(n)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mitgliederverzeichnis-Einträge ohne effektiven Leitungsträger als Co‑Option */
|
||||||
|
function filterDirectoryExcludingLead(directory, excludeLeadPid) {
|
||||||
|
const ex =
|
||||||
|
excludeLeadPid != null && excludeLeadPid !== '' && Number.isFinite(Number(excludeLeadPid))
|
||||||
|
? Number(excludeLeadPid)
|
||||||
|
: null
|
||||||
|
if (ex == null) return directory
|
||||||
|
return directory.filter((m) => Number(m.id) !== ex)
|
||||||
|
}
|
||||||
function TrainingPlanningPage() {
|
function TrainingPlanningPage() {
|
||||||
const { user } = useAuth()
|
const { user } = useAuth()
|
||||||
const [groups, setGroups] = useState([])
|
const [groups, setGroups] = useState([])
|
||||||
|
|
@ -123,7 +145,6 @@ function TrainingPlanningPage() {
|
||||||
const [planScope, setPlanScope] = useState('group')
|
const [planScope, setPlanScope] = useState('group')
|
||||||
const [assignedToMeOnly, setAssignedToMeOnly] = useState(false)
|
const [assignedToMeOnly, setAssignedToMeOnly] = useState(false)
|
||||||
const [clubDirectory, setClubDirectory] = useState([])
|
const [clubDirectory, setClubDirectory] = useState([])
|
||||||
const [meProfile, setMeProfile] = useState(null)
|
|
||||||
const [assignModalOpen, setAssignModalOpen] = useState(false)
|
const [assignModalOpen, setAssignModalOpen] = useState(false)
|
||||||
const [assignDraft, setAssignDraft] = useState({
|
const [assignDraft, setAssignDraft] = useState({
|
||||||
unit: null,
|
unit: null,
|
||||||
|
|
@ -241,39 +262,41 @@ function TrainingPlanningPage() {
|
||||||
const r = (user?.role || '').toLowerCase()
|
const r = (user?.role || '').toLowerCase()
|
||||||
if (r === 'admin' || r === 'superadmin') return true
|
if (r === 'admin' || r === 'superadmin') return true
|
||||||
if (selectedGroupClubIdMemo == null || !Number.isFinite(selectedGroupClubIdMemo)) return false
|
if (selectedGroupClubIdMemo == null || !Number.isFinite(selectedGroupClubIdMemo)) return false
|
||||||
const row = (meProfile?.clubs || []).find((c) => Number(c.id) === selectedGroupClubIdMemo)
|
const row = (user?.clubs || []).find((c) => Number(c.id) === selectedGroupClubIdMemo)
|
||||||
return Array.isArray(row?.roles) && row.roles.includes('club_admin')
|
return Array.isArray(row?.roles) && row.roles.includes('club_admin')
|
||||||
}, [user?.role, selectedGroupClubIdMemo, meProfile])
|
}, [user?.role, user?.clubs, selectedGroupClubIdMemo])
|
||||||
|
|
||||||
useEffect(() => {
|
const clubAdminClubIdSet = useMemo(() => {
|
||||||
if (!user?.id) {
|
const ids = []
|
||||||
setMeProfile(null)
|
for (const c of user?.clubs || []) {
|
||||||
return undefined
|
if (Array.isArray(c.roles) && c.roles.includes('club_admin')) {
|
||||||
|
const id = Number(c.id)
|
||||||
|
if (Number.isFinite(id)) ids.push(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let cancelled = false
|
return new Set(ids)
|
||||||
api
|
}, [user?.clubs])
|
||||||
.getCurrentProfile()
|
|
||||||
.then((p) => {
|
|
||||||
if (!cancelled) setMeProfile(p)
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
if (!cancelled) setMeProfile(null)
|
|
||||||
})
|
|
||||||
return () => {
|
|
||||||
cancelled = true
|
|
||||||
}
|
|
||||||
}, [user?.id])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const gid = parseInt(formData.group_id || selectedGroupId || '0', 10)
|
const gid = parseInt(formData.group_id || selectedGroupId || '0', 10)
|
||||||
const gModal = Number.isFinite(gid) && gid >= 1 ? groups.find((x) => x.id === gid) : null
|
const gModal = Number.isFinite(gid) && gid >= 1 ? groups.find((x) => x.id === gid) : null
|
||||||
const clubForModal = gModal?.club_id != null ? Number(gModal.club_id) : null
|
const clubForModal = gModal?.club_id != null ? Number(gModal.club_id) : null
|
||||||
|
|
||||||
|
let assignModalClubId = null
|
||||||
|
if (assignModalOpen && assignDraft.unit?.group_id != null) {
|
||||||
|
const ug = Number(assignDraft.unit.group_id)
|
||||||
|
const gAssign = Number.isFinite(ug) ? groups.find((x) => x.id === ug) : null
|
||||||
|
if (gAssign?.club_id != null) assignModalClubId = Number(gAssign.club_id)
|
||||||
|
}
|
||||||
|
|
||||||
const loadClubId =
|
const loadClubId =
|
||||||
showModal && clubForModal != null && Number.isFinite(clubForModal)
|
showModal && clubForModal != null && Number.isFinite(clubForModal)
|
||||||
? clubForModal
|
? clubForModal
|
||||||
: planScope === 'club' && canClubOrgTraining && selectedGroupClubIdMemo != null
|
: assignModalOpen && assignModalClubId != null && Number.isFinite(assignModalClubId)
|
||||||
? selectedGroupClubIdMemo
|
? assignModalClubId
|
||||||
: null
|
: canClubOrgTraining && selectedGroupClubIdMemo != null && Number.isFinite(selectedGroupClubIdMemo)
|
||||||
|
? selectedGroupClubIdMemo
|
||||||
|
: null
|
||||||
|
|
||||||
if (loadClubId == null || !Number.isFinite(loadClubId)) {
|
if (loadClubId == null || !Number.isFinite(loadClubId)) {
|
||||||
setClubDirectory([])
|
setClubDirectory([])
|
||||||
|
|
@ -296,10 +319,11 @@ function TrainingPlanningPage() {
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
showModal,
|
showModal,
|
||||||
|
assignModalOpen,
|
||||||
|
assignDraft.unit,
|
||||||
formData.group_id,
|
formData.group_id,
|
||||||
selectedGroupId,
|
selectedGroupId,
|
||||||
groups,
|
groups,
|
||||||
planScope,
|
|
||||||
canClubOrgTraining,
|
canClubOrgTraining,
|
||||||
selectedGroupClubIdMemo,
|
selectedGroupClubIdMemo,
|
||||||
])
|
])
|
||||||
|
|
@ -559,7 +583,15 @@ function TrainingPlanningPage() {
|
||||||
session_assistants_inherit:
|
session_assistants_inherit:
|
||||||
fullUnit.assistant_trainer_profile_ids == null ||
|
fullUnit.assistant_trainer_profile_ids == null ||
|
||||||
fullUnit.assistant_trainer_profile_ids === undefined,
|
fullUnit.assistant_trainer_profile_ids === undefined,
|
||||||
session_assistant_profile_ids: toNumList(fullUnit.assistant_trainer_profile_ids),
|
session_assistant_profile_ids: (() => {
|
||||||
|
const efLead =
|
||||||
|
fullUnit.effective_lead_trainer_profile_id != null
|
||||||
|
? Number(fullUnit.effective_lead_trainer_profile_id)
|
||||||
|
: null
|
||||||
|
let xs = toNumList(fullUnit.assistant_trainer_profile_ids)
|
||||||
|
if (efLead != null && Number.isFinite(efLead)) xs = xs.filter((id) => id !== efLead)
|
||||||
|
return xs
|
||||||
|
})(),
|
||||||
})
|
})
|
||||||
setShowModal(true)
|
setShowModal(true)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -596,6 +628,14 @@ function TrainingPlanningPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const openTrainerAssignModal = (unit) => {
|
const openTrainerAssignModal = (unit) => {
|
||||||
|
const effLead =
|
||||||
|
unit.effective_lead_trainer_profile_id != null
|
||||||
|
? Number(unit.effective_lead_trainer_profile_id)
|
||||||
|
: null
|
||||||
|
let coIds = toNumList(unit.assistant_trainer_profile_ids)
|
||||||
|
if (effLead != null && Number.isFinite(effLead)) {
|
||||||
|
coIds = coIds.filter((id) => id !== effLead)
|
||||||
|
}
|
||||||
setAssignDraft({
|
setAssignDraft({
|
||||||
unit,
|
unit,
|
||||||
lead_trainer_profile_id:
|
lead_trainer_profile_id:
|
||||||
|
|
@ -604,7 +644,7 @@ function TrainingPlanningPage() {
|
||||||
: '',
|
: '',
|
||||||
session_assistants_inherit:
|
session_assistants_inherit:
|
||||||
unit.assistant_trainer_profile_ids == null || unit.assistant_trainer_profile_ids === undefined,
|
unit.assistant_trainer_profile_ids == null || unit.assistant_trainer_profile_ids === undefined,
|
||||||
session_assistant_profile_ids: toNumList(unit.assistant_trainer_profile_ids),
|
session_assistant_profile_ids: coIds,
|
||||||
})
|
})
|
||||||
setAssignModalOpen(true)
|
setAssignModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
@ -701,7 +741,27 @@ function TrainingPlanningPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateFormField = (field, value) => {
|
const updateFormField = (field, value) => {
|
||||||
setFormData((prev) => ({ ...prev, [field]: value }))
|
setFormData((prev) => {
|
||||||
|
if (field !== 'lead_trainer_profile_id') return { ...prev, [field]: value }
|
||||||
|
const ts = typeof value === 'string' ? value.trim() : String(value ?? '').trim()
|
||||||
|
const strip = new Set()
|
||||||
|
if (ts !== '') {
|
||||||
|
const nid = parseInt(ts, 10)
|
||||||
|
if (Number.isFinite(nid)) strip.add(nid)
|
||||||
|
} else {
|
||||||
|
const gidParsed = parseInt(prev.group_id || selectedGroupId || '0', 10)
|
||||||
|
const gr =
|
||||||
|
Number.isFinite(gidParsed) && gidParsed >= 1
|
||||||
|
? groups.find((xg) => xg.id === gidParsed)
|
||||||
|
: null
|
||||||
|
if (gr?.trainer_id != null) {
|
||||||
|
const ht = Number(gr.trainer_id)
|
||||||
|
if (Number.isFinite(ht)) strip.add(ht)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const assistants = prev.session_assistant_profile_ids.filter((id) => !strip.has(id))
|
||||||
|
return { ...prev, lead_trainer_profile_id: value, session_assistant_profile_ids: assistants }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const calendarGridDays = useMemo(() => {
|
const calendarGridDays = useMemo(() => {
|
||||||
|
|
@ -729,6 +789,32 @@ function TrainingPlanningPage() {
|
||||||
return new Date(y, mo - 1, 1).toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })
|
return new Date(y, mo - 1, 1).toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })
|
||||||
}, [calendarMonthStr])
|
}, [calendarMonthStr])
|
||||||
|
|
||||||
|
const mayConfigureSessionAssignments = useCallback(
|
||||||
|
(unit) => {
|
||||||
|
if (!unit) return false
|
||||||
|
const pid = Number(user?.id)
|
||||||
|
if (!Number.isFinite(pid)) return false
|
||||||
|
const r = (user?.role || '').toLowerCase()
|
||||||
|
if (r === 'admin' || r === 'superadmin') return true
|
||||||
|
|
||||||
|
const gClub = unit.group_club_id != null ? Number(unit.group_club_id) : null
|
||||||
|
if (Number.isFinite(gClub) && clubAdminClubIdSet.has(gClub)) return true
|
||||||
|
|
||||||
|
const gid = Number(unit.group_id)
|
||||||
|
const g = groups.find((gr) => gr.id === gid)
|
||||||
|
if (!g) return false
|
||||||
|
|
||||||
|
const cb = unit.created_by != null ? Number(unit.created_by) : NaN
|
||||||
|
if (Number.isFinite(cb) && cb === pid) return true
|
||||||
|
|
||||||
|
const ht = g.trainer_id != null ? Number(g.trainer_id) : NaN
|
||||||
|
if (Number.isFinite(ht) && ht === pid) return true
|
||||||
|
|
||||||
|
return normalizeGroupCoTrainerIds(g.co_trainer_ids).includes(pid)
|
||||||
|
},
|
||||||
|
[user?.id, user?.role, groups, clubAdminClubIdSet]
|
||||||
|
)
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="app-page" style={{ padding: '2rem 0', textAlign: 'center' }}>
|
<div className="app-page" style={{ padding: '2rem 0', textAlign: 'center' }}>
|
||||||
|
|
@ -739,7 +825,39 @@ function TrainingPlanningPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedGroup = groups.find((g) => g.id === parseInt(selectedGroupId, 10))
|
const selectedGroup = groups.find((g) => g.id === parseInt(selectedGroupId, 10))
|
||||||
const showOrgTrainerAssignControls = planScope === 'club' && canClubOrgTraining
|
|
||||||
|
const gidTrainerForm = parseInt(formData.group_id || selectedGroupId || '0', 10)
|
||||||
|
const groupForTrainerForm =
|
||||||
|
Number.isFinite(gidTrainerForm) && gidTrainerForm >= 1
|
||||||
|
? groups.find((gr) => gr.id === gidTrainerForm)
|
||||||
|
: null
|
||||||
|
|
||||||
|
let formTrainerAssignLeadExcludeId = null
|
||||||
|
if (groupForTrainerForm?.trainer_id != null) formTrainerAssignLeadExcludeId = Number(groupForTrainerForm.trainer_id)
|
||||||
|
const leadDraftTrim = String(formData.lead_trainer_profile_id || '').trim()
|
||||||
|
if (leadDraftTrim !== '') {
|
||||||
|
const nl = parseInt(leadDraftTrim, 10)
|
||||||
|
if (Number.isFinite(nl)) formTrainerAssignLeadExcludeId = nl
|
||||||
|
}
|
||||||
|
if (editingUnit?.effective_lead_trainer_profile_id != null && leadDraftTrim === '') {
|
||||||
|
const el = Number(editingUnit.effective_lead_trainer_profile_id)
|
||||||
|
if (Number.isFinite(el)) formTrainerAssignLeadExcludeId = el
|
||||||
|
}
|
||||||
|
|
||||||
|
const clubDirectoryForCo = filterDirectoryExcludingLead(clubDirectory, formTrainerAssignLeadExcludeId)
|
||||||
|
|
||||||
|
let assignExcludeLeadPid = null
|
||||||
|
if (assignModalOpen && assignDraft.unit) {
|
||||||
|
const dl = String(assignDraft.lead_trainer_profile_id || '').trim()
|
||||||
|
if (dl !== '') {
|
||||||
|
const n = parseInt(dl, 10)
|
||||||
|
assignExcludeLeadPid = Number.isFinite(n) ? n : null
|
||||||
|
} else if (assignDraft.unit.effective_lead_trainer_profile_id != null) {
|
||||||
|
const n = Number(assignDraft.unit.effective_lead_trainer_profile_id)
|
||||||
|
assignExcludeLeadPid = Number.isFinite(n) ? n : null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const clubDirectoryForAssignCo = filterDirectoryExcludingLead(clubDirectory, assignExcludeLeadPid)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app-page">
|
<div className="app-page">
|
||||||
|
|
@ -1038,11 +1156,12 @@ function TrainingPlanningPage() {
|
||||||
Nur meine Zuordnung (Leitung / Co)
|
Nur meine Zuordnung (Leitung / Co)
|
||||||
</label>
|
</label>
|
||||||
<span style={{ fontSize: '0.78rem', color: 'var(--text3)', lineHeight: 1.4, flex: '1 1 240px' }}>
|
<span style={{ fontSize: '0.78rem', color: 'var(--text3)', lineHeight: 1.4, flex: '1 1 240px' }}>
|
||||||
„Ganzer Verein“ nutzt den Verein der gewählten Gruppe; neue Termine unten gelten weiter für die gewählte Gruppe.
|
„Ganzer Verein“ bezieht sich auf denselben Verein wie die gewählte Gruppe: Dort siehst du Termine mehrerer Gruppen; neu angelegte Termine gelten weiter für die gesondert gewählte Gruppe.
|
||||||
{planScope === 'club' && canClubOrgTraining ? (
|
{selectedGroupId ? (
|
||||||
<span style={{ display: 'block', marginTop: '6px', color: 'var(--text2)' }}>
|
<span style={{ display: 'block', marginTop: '6px', color: 'var(--text2)' }}>
|
||||||
Vereinsorganisation: Über <strong>Trainer zuweisen</strong> kannst du pro Termin die Leitung und Co-Trainer
|
Über <strong>Trainer</strong> oder <strong>Trainer zuweisen</strong>: Leitung und Co je Einheit bearbeitbar (berechtigt: Vereinsorganisation, Haupt-/Co‑Trainer der Gruppe sowie Erstellung der Einheit).
|
||||||
anpassen (auch in der Kalenderansicht).
|
Das Mitgliederverzeichnis listet nur <strong>eigene Vereinsmitglieder</strong>; die Leitung erscheint nicht unter Co‑Trainer.
|
||||||
|
Gasttrainer aus anderen Vereinen (Zugriff nur auf eine Session, nicht auf den Verein insgesamt) sind für später vorgesehen.
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -1307,7 +1426,7 @@ function TrainingPlanningPage() {
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
{showOrgTrainerAssignControls ? (
|
{mayConfigureSessionAssignments(unit) ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||||
|
|
@ -1504,7 +1623,7 @@ function TrainingPlanningPage() {
|
||||||
<button className="btn btn-secondary" onClick={() => handleEdit(unit)}>
|
<button className="btn btn-secondary" onClick={() => handleEdit(unit)}>
|
||||||
Bearbeiten
|
Bearbeiten
|
||||||
</button>
|
</button>
|
||||||
{showOrgTrainerAssignControls ? (
|
{mayConfigureSessionAssignments(unit) ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary"
|
className="btn btn-secondary"
|
||||||
|
|
@ -1594,9 +1713,25 @@ function TrainingPlanningPage() {
|
||||||
<select
|
<select
|
||||||
className="form-input"
|
className="form-input"
|
||||||
value={assignDraft.lead_trainer_profile_id}
|
value={assignDraft.lead_trainer_profile_id}
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
setAssignDraft((prev) => ({ ...prev, lead_trainer_profile_id: e.target.value }))
|
const v = e.target.value
|
||||||
}
|
setAssignDraft((prev) => {
|
||||||
|
const exclude = []
|
||||||
|
const tr = String(v || '').trim()
|
||||||
|
if (tr !== '') {
|
||||||
|
const n = parseInt(tr, 10)
|
||||||
|
if (Number.isFinite(n)) exclude.push(n)
|
||||||
|
} else if (prev.unit?.effective_lead_trainer_profile_id != null) {
|
||||||
|
const ef = Number(prev.unit.effective_lead_trainer_profile_id)
|
||||||
|
if (Number.isFinite(ef)) exclude.push(ef)
|
||||||
|
}
|
||||||
|
const exSet = new Set(exclude)
|
||||||
|
const co = exclude.length
|
||||||
|
? prev.session_assistant_profile_ids.filter((x) => !exSet.has(x))
|
||||||
|
: prev.session_assistant_profile_ids
|
||||||
|
return { ...prev, lead_trainer_profile_id: v, session_assistant_profile_ids: co }
|
||||||
|
})
|
||||||
|
}}
|
||||||
disabled={assignSaving}
|
disabled={assignSaving}
|
||||||
>
|
>
|
||||||
<option value="">Standard (Haupttrainer der Gruppe)</option>
|
<option value="">Standard (Haupttrainer der Gruppe)</option>
|
||||||
|
|
@ -1630,7 +1765,7 @@ function TrainingPlanningPage() {
|
||||||
</div>
|
</div>
|
||||||
{!assignDraft.session_assistants_inherit ? (
|
{!assignDraft.session_assistants_inherit ? (
|
||||||
<div style={{ marginTop: '10px', maxHeight: '180px', overflowY: 'auto' }}>
|
<div style={{ marginTop: '10px', maxHeight: '180px', overflowY: 'auto' }}>
|
||||||
{clubDirectory.map((m) => {
|
{clubDirectoryForAssignCo.map((m) => {
|
||||||
const mid = typeof m.id === 'number' ? m.id : parseInt(String(m.id), 10)
|
const mid = typeof m.id === 'number' ? m.id : parseInt(String(m.id), 10)
|
||||||
const labelText = `${(m.name || '').trim() || m.email || `Profil ${mid}`}`
|
const labelText = `${(m.name || '').trim() || m.email || `Profil ${mid}`}`
|
||||||
const isOn = Number.isFinite(mid) && assignDraft.session_assistant_profile_ids.includes(mid)
|
const isOn = Number.isFinite(mid) && assignDraft.session_assistant_profile_ids.includes(mid)
|
||||||
|
|
@ -2075,7 +2210,7 @@ function TrainingPlanningPage() {
|
||||||
</div>
|
</div>
|
||||||
{!formData.session_assistants_inherit ? (
|
{!formData.session_assistants_inherit ? (
|
||||||
<div style={{ marginTop: '10px', maxHeight: '200px', overflowY: 'auto' }}>
|
<div style={{ marginTop: '10px', maxHeight: '200px', overflowY: 'auto' }}>
|
||||||
{clubDirectory.map((m) => {
|
{clubDirectoryForCo.map((m) => {
|
||||||
const mid = typeof m.id === 'number' ? m.id : parseInt(String(m.id), 10)
|
const mid = typeof m.id === 'number' ? m.id : parseInt(String(m.id), 10)
|
||||||
const labelText = `${(m.name || '').trim() || m.email || `Profil ${mid}`}`
|
const labelText = `${(m.name || '').trim() || m.email || `Profil ${mid}`}`
|
||||||
const isOn = Number.isFinite(mid) && formData.session_assistant_profile_ids.includes(mid)
|
const isOn = Number.isFinite(mid) && formData.session_assistant_profile_ids.includes(mid)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user