Compare commits
No commits in common. "426efd4b83017b26602e8b4cbc5db666712fc455" and "a9a4c78a0e013702b8d69835ec2851366eaeb998" have entirely different histories.
426efd4b83
...
a9a4c78a0e
|
|
@ -142,8 +142,8 @@ def list_training_styles(
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
SELECT ts.*, ps.name as parent_style_name
|
SELECT ts.*, ps.name as parent_style_name
|
||||||
FROM style_directions ts
|
FROM training_styles ts
|
||||||
LEFT JOIN style_directions ps ON ts.parent_style_id = ps.id
|
LEFT JOIN training_styles ps ON ts.parent_style_id = ps.id
|
||||||
"""
|
"""
|
||||||
params = []
|
params = []
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ def create_training_style(data: dict, session=Depends(require_auth)):
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO style_directions (name, abbreviation, description, parent_style_id, sort_order, status)
|
INSERT INTO training_styles (name, abbreviation, description, parent_style_id, sort_order, status)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s)
|
VALUES (%s, %s, %s, %s, %s, %s)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
""", (
|
""", (
|
||||||
|
|
@ -190,8 +190,8 @@ def create_training_style(data: dict, session=Depends(require_auth)):
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT ts.*, ps.name as parent_style_name
|
SELECT ts.*, ps.name as parent_style_name
|
||||||
FROM style_directions ts
|
FROM training_styles ts
|
||||||
LEFT JOIN style_directions ps ON ts.parent_style_id = ps.id
|
LEFT JOIN training_styles ps ON ts.parent_style_id = ps.id
|
||||||
WHERE ts.id = %s
|
WHERE ts.id = %s
|
||||||
""", (style_id,))
|
""", (style_id,))
|
||||||
return r2d(cur.fetchone())
|
return r2d(cur.fetchone())
|
||||||
|
|
@ -208,7 +208,7 @@ def update_training_style(style_id: int, data: dict, session=Depends(require_aut
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
UPDATE style_directions SET
|
UPDATE training_styles SET
|
||||||
name = %s,
|
name = %s,
|
||||||
abbreviation = %s,
|
abbreviation = %s,
|
||||||
description = %s,
|
description = %s,
|
||||||
|
|
@ -231,8 +231,8 @@ def update_training_style(style_id: int, data: dict, session=Depends(require_aut
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT ts.*, ps.name as parent_style_name
|
SELECT ts.*, ps.name as parent_style_name
|
||||||
FROM style_directions ts
|
FROM training_styles ts
|
||||||
LEFT JOIN style_directions ps ON ts.parent_style_id = ps.id
|
LEFT JOIN training_styles ps ON ts.parent_style_id = ps.id
|
||||||
WHERE ts.id = %s
|
WHERE ts.id = %s
|
||||||
""", (style_id,))
|
""", (style_id,))
|
||||||
return r2d(cur.fetchone())
|
return r2d(cur.fetchone())
|
||||||
|
|
@ -247,7 +247,7 @@ def delete_training_style(style_id: int, session=Depends(require_auth)):
|
||||||
|
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
cur.execute("DELETE FROM style_directions WHERE id = %s", (style_id,))
|
cur.execute("DELETE FROM training_styles WHERE id = %s", (style_id,))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|
@ -830,7 +830,7 @@ def delete_target_group(target_group_id: int, session=Depends(require_auth)):
|
||||||
# Check if assigned to training styles (M:N)
|
# Check if assigned to training styles (M:N)
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT COUNT(*) as count
|
SELECT COUNT(*) as count
|
||||||
FROM style_direction_target_groups
|
FROM training_style_target_groups
|
||||||
WHERE target_group_id = %s
|
WHERE target_group_id = %s
|
||||||
""", (target_group_id,))
|
""", (target_group_id,))
|
||||||
style_count = cur.fetchone()['count']
|
style_count = cur.fetchone()['count']
|
||||||
|
|
@ -854,14 +854,14 @@ def delete_target_group(target_group_id: int, session=Depends(require_auth)):
|
||||||
|
|
||||||
@router.get("/training-style-target-groups")
|
@router.get("/training-style-target-groups")
|
||||||
def list_training_style_target_groups(
|
def list_training_style_target_groups(
|
||||||
style_direction_id: Optional[int] = Query(default=None),
|
training_style_id: Optional[int] = Query(default=None),
|
||||||
target_group_id: Optional[int] = Query(default=None),
|
target_group_id: Optional[int] = Query(default=None),
|
||||||
is_primary: Optional[bool] = Query(default=None),
|
is_primary: Optional[bool] = Query(default=None),
|
||||||
session=Depends(require_auth)
|
session=Depends(require_auth)
|
||||||
):
|
):
|
||||||
"""List M:N assignments between style directions and target groups.
|
"""List M:N assignments between training styles and target groups.
|
||||||
|
|
||||||
Returns enriched data with style_direction_name, target_group_name,
|
Returns enriched data with training_style_name, target_group_name,
|
||||||
focus_area_name for easy display in Matrix UI.
|
focus_area_name for easy display in Matrix UI.
|
||||||
"""
|
"""
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
|
|
@ -869,41 +869,41 @@ def list_training_style_target_groups(
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
SELECT
|
SELECT
|
||||||
sdtg.id,
|
tstg.id,
|
||||||
sdtg.style_direction_id,
|
tstg.training_style_id,
|
||||||
sdtg.target_group_id,
|
tstg.target_group_id,
|
||||||
sdtg.is_primary,
|
tstg.is_primary,
|
||||||
sdtg.created_at,
|
tstg.created_at,
|
||||||
sd.name as style_direction_name,
|
ts.name as training_style_name,
|
||||||
sd.focus_area_id,
|
ts.focus_area_id,
|
||||||
fa.name as focus_area_name,
|
fa.name as focus_area_name,
|
||||||
tg.name as target_group_name,
|
tg.name as target_group_name,
|
||||||
tg.min_age,
|
tg.min_age,
|
||||||
tg.max_age
|
tg.max_age
|
||||||
FROM style_direction_target_groups sdtg
|
FROM training_style_target_groups tstg
|
||||||
LEFT JOIN style_directions sd ON sdtg.style_direction_id = sd.id
|
LEFT JOIN training_styles ts ON tstg.training_style_id = ts.id
|
||||||
LEFT JOIN focus_areas fa ON sd.focus_area_id = fa.id
|
LEFT JOIN focus_areas fa ON ts.focus_area_id = fa.id
|
||||||
LEFT JOIN target_groups tg ON sdtg.target_group_id = tg.id
|
LEFT JOIN target_groups tg ON tstg.target_group_id = tg.id
|
||||||
"""
|
"""
|
||||||
params = []
|
params = []
|
||||||
where = []
|
where = []
|
||||||
|
|
||||||
if style_direction_id is not None:
|
if training_style_id is not None:
|
||||||
where.append("sdtg.style_direction_id = %s")
|
where.append("tstg.training_style_id = %s")
|
||||||
params.append(style_direction_id)
|
params.append(training_style_id)
|
||||||
|
|
||||||
if target_group_id is not None:
|
if target_group_id is not None:
|
||||||
where.append("sdtg.target_group_id = %s")
|
where.append("tstg.target_group_id = %s")
|
||||||
params.append(target_group_id)
|
params.append(target_group_id)
|
||||||
|
|
||||||
if is_primary is not None:
|
if is_primary is not None:
|
||||||
where.append("sdtg.is_primary = %s")
|
where.append("tstg.is_primary = %s")
|
||||||
params.append(is_primary)
|
params.append(is_primary)
|
||||||
|
|
||||||
if where:
|
if where:
|
||||||
query += " WHERE " + " AND ".join(where)
|
query += " WHERE " + " AND ".join(where)
|
||||||
|
|
||||||
query += " ORDER BY fa.sort_order, sd.sort_order, tg.sort_order"
|
query += " ORDER BY fa.sort_order, ts.sort_order, tg.sort_order"
|
||||||
|
|
||||||
cur.execute(query, params)
|
cur.execute(query, params)
|
||||||
rows = cur.fetchall()
|
rows = cur.fetchall()
|
||||||
|
|
@ -912,7 +912,7 @@ def list_training_style_target_groups(
|
||||||
|
|
||||||
@router.post("/training-style-target-groups")
|
@router.post("/training-style-target-groups")
|
||||||
def create_training_style_target_group(data: dict, session=Depends(require_auth)):
|
def create_training_style_target_group(data: dict, session=Depends(require_auth)):
|
||||||
"""Assign target group to style direction (admin only).
|
"""Assign target group to training style (admin only).
|
||||||
|
|
||||||
Uses UPSERT logic - if assignment exists, updates is_primary flag.
|
Uses UPSERT logic - if assignment exists, updates is_primary flag.
|
||||||
"""
|
"""
|
||||||
|
|
@ -920,25 +920,25 @@ def create_training_style_target_group(data: dict, session=Depends(require_auth)
|
||||||
if role not in ['admin', 'superadmin']:
|
if role not in ['admin', 'superadmin']:
|
||||||
raise HTTPException(403, "Nur Admins dürfen Zuordnungen erstellen")
|
raise HTTPException(403, "Nur Admins dürfen Zuordnungen erstellen")
|
||||||
|
|
||||||
style_direction_id = data.get('style_direction_id')
|
training_style_id = data.get('training_style_id')
|
||||||
target_group_id = data.get('target_group_id')
|
target_group_id = data.get('target_group_id')
|
||||||
|
|
||||||
if not style_direction_id or not target_group_id:
|
if not training_style_id or not target_group_id:
|
||||||
raise HTTPException(400, "style_direction_id und target_group_id sind Pflichtfelder")
|
raise HTTPException(400, "training_style_id und target_group_id sind Pflichtfelder")
|
||||||
|
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
|
|
||||||
# Upsert logic
|
# Upsert logic
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
INSERT INTO style_direction_target_groups
|
INSERT INTO training_style_target_groups
|
||||||
(style_direction_id, target_group_id, is_primary)
|
(training_style_id, target_group_id, is_primary)
|
||||||
VALUES (%s, %s, %s)
|
VALUES (%s, %s, %s)
|
||||||
ON CONFLICT (style_direction_id, target_group_id)
|
ON CONFLICT (training_style_id, target_group_id)
|
||||||
DO UPDATE SET is_primary = EXCLUDED.is_primary
|
DO UPDATE SET is_primary = EXCLUDED.is_primary
|
||||||
RETURNING id
|
RETURNING id
|
||||||
""", (
|
""", (
|
||||||
style_direction_id,
|
training_style_id,
|
||||||
target_group_id,
|
target_group_id,
|
||||||
data.get('is_primary', False)
|
data.get('is_primary', False)
|
||||||
))
|
))
|
||||||
|
|
@ -949,20 +949,20 @@ def create_training_style_target_group(data: dict, session=Depends(require_auth)
|
||||||
# Return enriched record
|
# Return enriched record
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
sdtg.id,
|
tstg.id,
|
||||||
sdtg.style_direction_id,
|
tstg.training_style_id,
|
||||||
sdtg.target_group_id,
|
tstg.target_group_id,
|
||||||
sdtg.is_primary,
|
tstg.is_primary,
|
||||||
sdtg.created_at,
|
tstg.created_at,
|
||||||
sd.name as style_direction_name,
|
ts.name as training_style_name,
|
||||||
sd.focus_area_id,
|
ts.focus_area_id,
|
||||||
fa.name as focus_area_name,
|
fa.name as focus_area_name,
|
||||||
tg.name as target_group_name
|
tg.name as target_group_name
|
||||||
FROM style_direction_target_groups sdtg
|
FROM training_style_target_groups tstg
|
||||||
LEFT JOIN style_directions sd ON sdtg.style_direction_id = sd.id
|
LEFT JOIN training_styles ts ON tstg.training_style_id = ts.id
|
||||||
LEFT JOIN focus_areas fa ON sd.focus_area_id = fa.id
|
LEFT JOIN focus_areas fa ON ts.focus_area_id = fa.id
|
||||||
LEFT JOIN target_groups tg ON sdtg.target_group_id = tg.id
|
LEFT JOIN target_groups tg ON tstg.target_group_id = tg.id
|
||||||
WHERE sdtg.id = %s
|
WHERE tstg.id = %s
|
||||||
""", (assignment_id,))
|
""", (assignment_id,))
|
||||||
|
|
||||||
return r2d(cur.fetchone())
|
return r2d(cur.fetchone())
|
||||||
|
|
@ -986,7 +986,7 @@ def update_training_style_target_group(
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
|
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
UPDATE style_direction_target_groups
|
UPDATE training_style_target_groups
|
||||||
SET is_primary = %s
|
SET is_primary = %s
|
||||||
WHERE id = %s
|
WHERE id = %s
|
||||||
""", (
|
""", (
|
||||||
|
|
@ -999,20 +999,20 @@ def update_training_style_target_group(
|
||||||
# Return enriched record
|
# Return enriched record
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
sdtg.id,
|
tstg.id,
|
||||||
sdtg.style_direction_id,
|
tstg.training_style_id,
|
||||||
sdtg.target_group_id,
|
tstg.target_group_id,
|
||||||
sdtg.is_primary,
|
tstg.is_primary,
|
||||||
sdtg.created_at,
|
tstg.created_at,
|
||||||
sd.name as style_direction_name,
|
ts.name as training_style_name,
|
||||||
sd.focus_area_id,
|
ts.focus_area_id,
|
||||||
fa.name as focus_area_name,
|
fa.name as focus_area_name,
|
||||||
tg.name as target_group_name
|
tg.name as target_group_name
|
||||||
FROM style_direction_target_groups sdtg
|
FROM training_style_target_groups tstg
|
||||||
LEFT JOIN style_directions sd ON sdtg.style_direction_id = sd.id
|
LEFT JOIN training_styles ts ON tstg.training_style_id = ts.id
|
||||||
LEFT JOIN focus_areas fa ON sd.focus_area_id = fa.id
|
LEFT JOIN focus_areas fa ON ts.focus_area_id = fa.id
|
||||||
LEFT JOIN target_groups tg ON sdtg.target_group_id = tg.id
|
LEFT JOIN target_groups tg ON tstg.target_group_id = tg.id
|
||||||
WHERE sdtg.id = %s
|
WHERE tstg.id = %s
|
||||||
""", (assignment_id,))
|
""", (assignment_id,))
|
||||||
|
|
||||||
return r2d(cur.fetchone())
|
return r2d(cur.fetchone())
|
||||||
|
|
@ -1027,7 +1027,7 @@ def delete_training_style_target_group(assignment_id: int, session=Depends(requi
|
||||||
|
|
||||||
with get_db() as conn:
|
with get_db() as conn:
|
||||||
cur = get_cursor(conn)
|
cur = get_cursor(conn)
|
||||||
cur.execute("DELETE FROM style_direction_target_groups WHERE id = %s", (assignment_id,))
|
cur.execute("DELETE FROM training_style_target_groups WHERE id = %s", (assignment_id,))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|
@ -1038,7 +1038,7 @@ def get_training_styles_hierarchy(
|
||||||
status: Optional[str] = Query(default='active'),
|
status: Optional[str] = Query(default='active'),
|
||||||
session=Depends(require_auth)
|
session=Depends(require_auth)
|
||||||
):
|
):
|
||||||
"""Get hierarchical structure: Focus Areas → Style Directions → Target Groups.
|
"""Get hierarchical structure: Focus Areas → Training Styles → Target Groups.
|
||||||
|
|
||||||
Returns nested structure for Tree-View rendering in Admin UI.
|
Returns nested structure for Tree-View rendering in Admin UI.
|
||||||
"""
|
"""
|
||||||
|
|
@ -1058,25 +1058,25 @@ def get_training_styles_hierarchy(
|
||||||
cur.execute(fa_query, fa_params)
|
cur.execute(fa_query, fa_params)
|
||||||
focus_areas = [r2d(r) for r in cur.fetchall()]
|
focus_areas = [r2d(r) for r in cur.fetchall()]
|
||||||
|
|
||||||
# For each focus area, get style directions with their target groups
|
# For each focus area, get training styles with their target groups
|
||||||
for fa in focus_areas:
|
for fa in focus_areas:
|
||||||
sd_query = """
|
ts_query = """
|
||||||
SELECT * FROM style_directions
|
SELECT * FROM training_styles
|
||||||
WHERE focus_area_id = %s
|
WHERE focus_area_id = %s
|
||||||
"""
|
"""
|
||||||
sd_params = [fa['id']]
|
ts_params = [fa['id']]
|
||||||
|
|
||||||
if status:
|
if status:
|
||||||
sd_query += " AND status = %s"
|
ts_query += " AND status = %s"
|
||||||
sd_params.append(status)
|
ts_params.append(status)
|
||||||
|
|
||||||
sd_query += " ORDER BY sort_order, name"
|
ts_query += " ORDER BY sort_order, name"
|
||||||
|
|
||||||
cur.execute(sd_query, sd_params)
|
cur.execute(ts_query, ts_params)
|
||||||
style_directions = [r2d(r) for r in cur.fetchall()]
|
training_styles = [r2d(r) for r in cur.fetchall()]
|
||||||
|
|
||||||
# For each style direction, get assigned target groups
|
# For each training style, get assigned target groups
|
||||||
for sd in style_directions:
|
for ts in training_styles:
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
tg.id,
|
tg.id,
|
||||||
|
|
@ -1084,16 +1084,16 @@ def get_training_styles_hierarchy(
|
||||||
tg.description,
|
tg.description,
|
||||||
tg.min_age,
|
tg.min_age,
|
||||||
tg.max_age,
|
tg.max_age,
|
||||||
sdtg.is_primary,
|
tstg.is_primary,
|
||||||
sdtg.id as assignment_id
|
tstg.id as assignment_id
|
||||||
FROM style_direction_target_groups sdtg
|
FROM training_style_target_groups tstg
|
||||||
LEFT JOIN target_groups tg ON sdtg.target_group_id = tg.id
|
LEFT JOIN target_groups tg ON tstg.target_group_id = tg.id
|
||||||
WHERE sdtg.style_direction_id = %s
|
WHERE tstg.training_style_id = %s
|
||||||
ORDER BY tg.sort_order, tg.name
|
ORDER BY tg.sort_order, tg.name
|
||||||
""", (sd['id'],))
|
""", (ts['id'],))
|
||||||
|
|
||||||
sd['target_groups'] = [r2d(r) for r in cur.fetchall()]
|
ts['target_groups'] = [r2d(r) for r in cur.fetchall()]
|
||||||
|
|
||||||
fa['style_directions'] = style_directions
|
fa['training_styles'] = training_styles
|
||||||
|
|
||||||
return focus_areas
|
return focus_areas
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ MODULE_VERSIONS = {
|
||||||
"import_wiki": "0.1.0",
|
"import_wiki": "0.1.0",
|
||||||
"admin": "1.0.0",
|
"admin": "1.0.0",
|
||||||
"membership": "1.0.0",
|
"membership": "1.0.0",
|
||||||
"catalogs": "1.4.0", # Updated: Backend SQL Queries für renamed tables (Migration 010+011)
|
"catalogs": "1.3.0", # Updated: M:N Zielgruppen-Zuordnung (Migration 009)
|
||||||
}
|
}
|
||||||
|
|
||||||
CHANGELOG = [
|
CHANGELOG = [
|
||||||
|
|
@ -32,9 +32,7 @@ CHANGELOG = [
|
||||||
"DB: Neue Tabelle training_types mit Seed-Daten (Breitensport, Leistungssport, Wettkampf)",
|
"DB: Neue Tabelle training_types mit Seed-Daten (Breitensport, Leistungssport, Wettkampf)",
|
||||||
"DB: Neue Junction-Tabelle exercise_training_types (M:N)",
|
"DB: Neue Junction-Tabelle exercise_training_types (M:N)",
|
||||||
"Architektur: Fokusbereich → Stilrichtung → Trainingsstil → Zielgruppe (alle M:N)",
|
"Architektur: Fokusbereich → Stilrichtung → Trainingsstil → Zielgruppe (alle M:N)",
|
||||||
"Backend: Alle SQL Queries aktualisiert auf neue Tabellennamen (style_directions, style_direction_target_groups)",
|
"Phase 1: Nur Datenbank-Migrationen - Backend/Frontend-Updates folgen",
|
||||||
"Backend: API Parameter umbenannt (training_style_id → style_direction_id)",
|
|
||||||
"Backend: CRUD Endpoints für training_types hinzugefügt",
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export default function AdminCatalogsPage() {
|
||||||
const data = await api.listFocusAreas()
|
const data = await api.listFocusAreas()
|
||||||
setFocusAreas(data)
|
setFocusAreas(data)
|
||||||
} else if (activeTab === 'training-styles') {
|
} else if (activeTab === 'training-styles') {
|
||||||
const data = await api.listStyleDirections()
|
const data = await api.listTrainingStyles()
|
||||||
setTrainingStyles(data)
|
setTrainingStyles(data)
|
||||||
} else if (activeTab === 'training-characters') {
|
} else if (activeTab === 'training-characters') {
|
||||||
const data = await api.listTrainingCharacters()
|
const data = await api.listTrainingCharacters()
|
||||||
|
|
@ -85,13 +85,13 @@ export default function AdminCatalogsPage() {
|
||||||
setProfiles(profs)
|
setProfiles(profs)
|
||||||
setFocusAreas(areas)
|
setFocusAreas(areas)
|
||||||
} else if (activeTab === 'hierarchy') {
|
} else if (activeTab === 'hierarchy') {
|
||||||
const data = await api.getStyleDirectionsHierarchy()
|
const data = await api.getTrainingStylesHierarchy()
|
||||||
setHierarchyData(data)
|
setHierarchyData(data)
|
||||||
} else if (activeTab === 'target-groups-matrix') {
|
} else if (activeTab === 'target-groups-matrix') {
|
||||||
const [styles, groups, assigns] = await Promise.all([
|
const [styles, groups, assigns] = await Promise.all([
|
||||||
api.listStyleDirections(),
|
api.listTrainingStyles(),
|
||||||
api.listTargetGroups(),
|
api.listTargetGroups(),
|
||||||
api.listStyleDirectionTargetGroups()
|
api.listTrainingStyleTargetGroups()
|
||||||
])
|
])
|
||||||
setTrainingStyles(styles)
|
setTrainingStyles(styles)
|
||||||
setTargetGroups(groups)
|
setTargetGroups(groups)
|
||||||
|
|
@ -135,10 +135,10 @@ export default function AdminCatalogsPage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Style Directions (formerly Training Styles)
|
// Training Styles
|
||||||
async function createStyleDirection() {
|
async function createTrainingStyle() {
|
||||||
try {
|
try {
|
||||||
await api.createStyleDirection(newTS)
|
await api.createTrainingStyle(newTS)
|
||||||
setNewTS({ name: '', description: '', parent_style_id: null })
|
setNewTS({ name: '', description: '', parent_style_id: null })
|
||||||
loadData()
|
loadData()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -146,9 +146,9 @@ export default function AdminCatalogsPage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateStyleDirection(id, data) {
|
async function updateTrainingStyle(id, data) {
|
||||||
try {
|
try {
|
||||||
await api.updateStyleDirection(id, data)
|
await api.updateTrainingStyle(id, data)
|
||||||
setEditingTS(null)
|
setEditingTS(null)
|
||||||
loadData()
|
loadData()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -156,10 +156,10 @@ export default function AdminCatalogsPage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteStyleDirection(id) {
|
async function deleteTrainingStyle(id) {
|
||||||
if (!confirm('Stilrichtung wirklich löschen?')) return
|
if (!confirm('Trainingsstil wirklich löschen?')) return
|
||||||
try {
|
try {
|
||||||
await api.deleteStyleDirection(id)
|
await api.deleteTrainingStyle(id)
|
||||||
loadData()
|
loadData()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e.message)
|
setError(e.message)
|
||||||
|
|
@ -1046,14 +1046,14 @@ export default function AdminCatalogsPage() {
|
||||||
<div>
|
<div>
|
||||||
<h3 style={{ margin: 0 }}>{fa.name}</h3>
|
<h3 style={{ margin: 0 }}>{fa.name}</h3>
|
||||||
<p style={{ margin: '4px 0 0 0', fontSize: '14px', color: 'var(--text2)' }}>
|
<p style={{ margin: '4px 0 0 0', fontSize: '14px', color: 'var(--text2)' }}>
|
||||||
{fa.style_directions?.length || 0} Trainingsstil(e)
|
{fa.training_styles?.length || 0} Trainingsstil(e)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{expandedNodes.has(`fa-${fa.id}`) && fa.style_directions && fa.style_directions.length > 0 && (
|
{expandedNodes.has(`fa-${fa.id}`) && fa.training_styles && fa.training_styles.length > 0 && (
|
||||||
<div style={{ marginLeft: '40px', marginTop: '12px', borderLeft: '2px solid var(--border)', paddingLeft: '16px' }}>
|
<div style={{ marginLeft: '40px', marginTop: '12px', borderLeft: '2px solid var(--border)', paddingLeft: '16px' }}>
|
||||||
{fa.style_directions.map(ts => (
|
{fa.training_styles.map(ts => (
|
||||||
<div key={ts.id} style={{ marginBottom: '12px' }}>
|
<div key={ts.id} style={{ marginBottom: '12px' }}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|
@ -1175,7 +1175,7 @@ export default function AdminCatalogsPage() {
|
||||||
</td>
|
</td>
|
||||||
{targetGroups.map(tg => {
|
{targetGroups.map(tg => {
|
||||||
const assignment = assignments.find(
|
const assignment = assignments.find(
|
||||||
a => a.style_direction_id === ts.id && a.target_group_id === tg.id
|
a => a.training_style_id === ts.id && a.target_group_id === tg.id
|
||||||
)
|
)
|
||||||
const isAssigned = !!assignment
|
const isAssigned = !!assignment
|
||||||
|
|
||||||
|
|
@ -1187,10 +1187,10 @@ export default function AdminCatalogsPage() {
|
||||||
onChange={async () => {
|
onChange={async () => {
|
||||||
try {
|
try {
|
||||||
if (isAssigned) {
|
if (isAssigned) {
|
||||||
await api.deleteStyleDirectionTargetGroup(assignment.id)
|
await api.deleteTrainingStyleTargetGroup(assignment.id)
|
||||||
} else {
|
} else {
|
||||||
await api.createStyleDirectionTargetGroup({
|
await api.createTrainingStyleTargetGroup({
|
||||||
style_direction_id: ts.id,
|
training_style_id: ts.id,
|
||||||
target_group_id: tg.id,
|
target_group_id: tg.id,
|
||||||
is_primary: false
|
is_primary: false
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -257,27 +257,27 @@ export async function deleteFocusArea(id) {
|
||||||
return request(`/api/focus-areas/${id}`, { method: 'DELETE' })
|
return request(`/api/focus-areas/${id}`, { method: 'DELETE' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Style Directions (formerly Training Styles)
|
// Training Styles
|
||||||
export async function listStyleDirections(filters = {}) {
|
export async function listTrainingStyles(filters = {}) {
|
||||||
const query = new URLSearchParams(filters).toString()
|
const query = new URLSearchParams(filters).toString()
|
||||||
return request(`/api/training-styles${query ? '?' + query : ''}`)
|
return request(`/api/training-styles${query ? '?' + query : ''}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createStyleDirection(data) {
|
export async function createTrainingStyle(data) {
|
||||||
return request('/api/training-styles', {
|
return request('/api/training-styles', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateStyleDirection(id, data) {
|
export async function updateTrainingStyle(id, data) {
|
||||||
return request(`/api/training-styles/${id}`, {
|
return request(`/api/training-styles/${id}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteStyleDirection(id) {
|
export async function deleteTrainingStyle(id) {
|
||||||
return request(`/api/training-styles/${id}`, { method: 'DELETE' })
|
return request(`/api/training-styles/${id}`, { method: 'DELETE' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,31 +394,31 @@ export async function deleteTargetGroup(id) {
|
||||||
return request(`/api/target-groups/${id}`, { method: 'DELETE' })
|
return request(`/api/target-groups/${id}`, { method: 'DELETE' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Style Direction → Target Groups (M:N Assignments)
|
// Training Style → Target Groups (M:N Assignments)
|
||||||
export async function listStyleDirectionTargetGroups(filters = {}) {
|
export async function listTrainingStyleTargetGroups(filters = {}) {
|
||||||
const query = new URLSearchParams(filters).toString()
|
const query = new URLSearchParams(filters).toString()
|
||||||
return request(`/api/training-style-target-groups${query ? '?' + query : ''}`)
|
return request(`/api/training-style-target-groups${query ? '?' + query : ''}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createStyleDirectionTargetGroup(data) {
|
export async function createTrainingStyleTargetGroup(data) {
|
||||||
return request('/api/training-style-target-groups', {
|
return request('/api/training-style-target-groups', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateStyleDirectionTargetGroup(id, data) {
|
export async function updateTrainingStyleTargetGroup(id, data) {
|
||||||
return request(`/api/training-style-target-groups/${id}`, {
|
return request(`/api/training-style-target-groups/${id}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteStyleDirectionTargetGroup(id) {
|
export async function deleteTrainingStyleTargetGroup(id) {
|
||||||
return request(`/api/training-style-target-groups/${id}`, { method: 'DELETE' })
|
return request(`/api/training-style-target-groups/${id}`, { method: 'DELETE' })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStyleDirectionsHierarchy(filters = {}) {
|
export async function getTrainingStylesHierarchy(filters = {}) {
|
||||||
const query = new URLSearchParams(filters).toString()
|
const query = new URLSearchParams(filters).toString()
|
||||||
return request(`/api/training-styles/hierarchy${query ? '?' + query : ''}`)
|
return request(`/api/training-styles/hierarchy${query ? '?' + query : ''}`)
|
||||||
}
|
}
|
||||||
|
|
@ -528,10 +528,10 @@ export const api = {
|
||||||
createFocusArea,
|
createFocusArea,
|
||||||
updateFocusArea,
|
updateFocusArea,
|
||||||
deleteFocusArea,
|
deleteFocusArea,
|
||||||
listStyleDirections,
|
listTrainingStyles,
|
||||||
createStyleDirection,
|
createTrainingStyle,
|
||||||
updateStyleDirection,
|
updateTrainingStyle,
|
||||||
deleteStyleDirection,
|
deleteTrainingStyle,
|
||||||
listTrainingCharacters,
|
listTrainingCharacters,
|
||||||
createTrainingCharacter,
|
createTrainingCharacter,
|
||||||
updateTrainingCharacter,
|
updateTrainingCharacter,
|
||||||
|
|
@ -551,11 +551,11 @@ export const api = {
|
||||||
createTargetGroup,
|
createTargetGroup,
|
||||||
updateTargetGroup,
|
updateTargetGroup,
|
||||||
deleteTargetGroup,
|
deleteTargetGroup,
|
||||||
listStyleDirectionTargetGroups,
|
listTrainingStyleTargetGroups,
|
||||||
createStyleDirectionTargetGroup,
|
createTrainingStyleTargetGroup,
|
||||||
updateStyleDirectionTargetGroup,
|
updateTrainingStyleTargetGroup,
|
||||||
deleteStyleDirectionTargetGroup,
|
deleteTrainingStyleTargetGroup,
|
||||||
getStyleDirectionsHierarchy,
|
getTrainingStylesHierarchy,
|
||||||
|
|
||||||
// System
|
// System
|
||||||
getVersion,
|
getVersion,
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,5 @@ export const PAGE_VERSIONS = {
|
||||||
ClubsPage: "1.0.0",
|
ClubsPage: "1.0.0",
|
||||||
SkillsPage: "1.0.0",
|
SkillsPage: "1.0.0",
|
||||||
TrainingPlanningPage: "1.0.0",
|
TrainingPlanningPage: "1.0.0",
|
||||||
AdminCatalogsPage: "2.2.0", // Updated: Frontend API Calls & Field Names für renamed tables
|
AdminCatalogsPage: "2.1.0", // Updated: Stilrichtungen + Trainingsstil-Dimension
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user