feat: update version to 0.8.0 and enhance training planning features
- Incremented application version to 0.8.0 and updated database schema version to 20260428031. - Introduced support for training plan templates, allowing users to create and manage reusable training structures. - Enhanced the Training Planning UI to include sections and exercises, improving the organization of training units. - Updated API endpoints for training plan templates, enabling CRUD operations for better integration with the frontend. - Improved validation and permission checks for creating training units, ensuring proper access control.
This commit is contained in:
parent
7134fd1a25
commit
d7e1a82a37
113
backend/migrations/031_training_plan_templates_and_sections.sql
Normal file
113
backend/migrations/031_training_plan_templates_and_sections.sql
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
-- Migration 031: Trainingsvorlagen (Sektionen) und strukturierter Ablauf pro Einheit
|
||||
-- Freie Anmerkungszeilen (note) zwischen Übungen (exercise) mit optionaler Variante/Dauer.
|
||||
|
||||
-- ── Vorlagen (wiederverwendbare Gliederung für Gruppen/Trainer) ─────────────
|
||||
CREATE TABLE IF NOT EXISTS training_plan_templates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
club_id INT REFERENCES clubs(id) ON DELETE SET NULL,
|
||||
created_by INT REFERENCES profiles(id) ON DELETE SET NULL,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS training_plan_template_sections (
|
||||
id SERIAL PRIMARY KEY,
|
||||
template_id INT NOT NULL REFERENCES training_plan_templates(id) ON DELETE CASCADE,
|
||||
order_index INT NOT NULL,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
guidance_text TEXT,
|
||||
UNIQUE (template_id, order_index)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_training_plan_templates_club ON training_plan_templates(club_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_training_plan_templates_creator ON training_plan_templates(created_by);
|
||||
CREATE INDEX IF NOT EXISTS idx_training_plan_template_sections_template ON training_plan_template_sections(template_id);
|
||||
|
||||
DROP TRIGGER IF EXISTS training_plan_templates_update ON training_plan_templates;
|
||||
CREATE TRIGGER training_plan_templates_update
|
||||
BEFORE UPDATE ON training_plan_templates
|
||||
FOR EACH ROW EXECUTE FUNCTION update_timestamp();
|
||||
|
||||
-- ── Verknüpfung Einheit ↔ genutzte Vorlage (nur Metadaten) ──────────────────
|
||||
ALTER TABLE training_units
|
||||
ADD COLUMN IF NOT EXISTS plan_template_id INT REFERENCES training_plan_templates(id) ON DELETE SET NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_training_units_plan_template ON training_units(plan_template_id);
|
||||
|
||||
-- ── Konkrete Sektionen je Trainingseinheit ────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS training_unit_sections (
|
||||
id SERIAL PRIMARY KEY,
|
||||
training_unit_id INT NOT NULL REFERENCES training_units(id) ON DELETE CASCADE,
|
||||
order_index INT NOT NULL,
|
||||
title VARCHAR(200) NOT NULL DEFAULT 'Abschnitt',
|
||||
guidance_notes TEXT,
|
||||
source_template_section_id INT REFERENCES training_plan_template_sections(id) ON DELETE SET NULL,
|
||||
UNIQUE (training_unit_id, order_index)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_training_unit_sections_unit ON training_unit_sections(training_unit_id);
|
||||
|
||||
-- ── Positionen: Übung oder freie Anmerkung ────────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS training_unit_section_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
section_id INT NOT NULL REFERENCES training_unit_sections(id) ON DELETE CASCADE,
|
||||
order_index INT NOT NULL,
|
||||
item_type VARCHAR(20) NOT NULL CHECK (item_type IN ('exercise', 'note')),
|
||||
exercise_id INT REFERENCES exercises(id) ON DELETE SET NULL,
|
||||
exercise_variant_id INT REFERENCES exercise_variants(id) ON DELETE SET NULL,
|
||||
planned_duration_min INT,
|
||||
actual_duration_min INT,
|
||||
notes TEXT,
|
||||
modifications TEXT,
|
||||
note_body TEXT,
|
||||
UNIQUE (section_id, order_index),
|
||||
CHECK (
|
||||
(item_type = 'exercise' AND exercise_id IS NOT NULL AND note_body IS NULL)
|
||||
OR
|
||||
(item_type = 'note' AND exercise_id IS NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_training_unit_section_items_section ON training_unit_section_items(section_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_training_unit_section_items_exercise ON training_unit_section_items(exercise_id)
|
||||
WHERE exercise_id IS NOT NULL;
|
||||
|
||||
-- ── Bestehende Zeilen migrieren: eine Sektion „Übungen“ pro Einheit ─────────
|
||||
INSERT INTO training_unit_sections (training_unit_id, order_index, title)
|
||||
SELECT id, 0, 'Übungen'
|
||||
FROM training_units tu
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM training_unit_sections tus WHERE tus.training_unit_id = tu.id
|
||||
);
|
||||
|
||||
INSERT INTO training_unit_section_items (
|
||||
section_id,
|
||||
order_index,
|
||||
item_type,
|
||||
exercise_id,
|
||||
exercise_variant_id,
|
||||
planned_duration_min,
|
||||
actual_duration_min,
|
||||
notes,
|
||||
modifications,
|
||||
note_body
|
||||
)
|
||||
SELECT
|
||||
tus.id,
|
||||
tue.order_index,
|
||||
'exercise',
|
||||
tue.exercise_id,
|
||||
tue.exercise_variant_id,
|
||||
tue.planned_duration_min,
|
||||
tue.actual_duration_min,
|
||||
tue.notes,
|
||||
tue.modifications,
|
||||
NULL
|
||||
FROM training_unit_exercises tue
|
||||
INNER JOIN training_unit_sections tus
|
||||
ON tus.training_unit_id = tue.training_unit_id
|
||||
AND tus.order_index = 0;
|
||||
|
||||
DROP TABLE IF EXISTS training_unit_exercises;
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,8 @@
|
|||
# Shinkan Jinkendo Version Information
|
||||
|
||||
APP_VERSION = "0.7.9"
|
||||
BUILD_DATE = "2026-04-27"
|
||||
DB_SCHEMA_VERSION = "20260427030"
|
||||
APP_VERSION = "0.8.0"
|
||||
BUILD_DATE = "2026-04-28"
|
||||
DB_SCHEMA_VERSION = "20260428031"
|
||||
|
||||
MODULE_VERSIONS = {
|
||||
"auth": "1.0.0",
|
||||
|
|
@ -14,7 +14,7 @@ MODULE_VERSIONS = {
|
|||
"exercises": "2.1.0", # Varianten-CRUD API + UI; Listen mit include_variants
|
||||
"training_units": "0.1.0",
|
||||
"training_programs": "0.1.0",
|
||||
"planning": "0.2.0",
|
||||
"planning": "0.3.0",
|
||||
"import_wiki": "1.0.0",
|
||||
"admin": "1.0.0",
|
||||
"membership": "1.0.0",
|
||||
|
|
@ -24,7 +24,14 @@ MODULE_VERSIONS = {
|
|||
|
||||
CHANGELOG = [
|
||||
{
|
||||
"version": "0.7.9",
|
||||
"version": "0.8.0",
|
||||
"date": "2026-04-28",
|
||||
"changes": [
|
||||
"DB 031: Trainingsvorlagen (Sektionen) + Struktur pro Einheit (Sektionen, Übungen/Notizen, Dauer)",
|
||||
"API: /api/training-plan-templates CRUD; Trainingseinheiten mit sections[] + plan_template_id",
|
||||
"Trainingsplanung UI: Abschnitte, Zwischen-Anmerkungen, Vorlagen auswählen / speichern",
|
||||
],
|
||||
},
|
||||
"date": "2026-04-27",
|
||||
"changes": [
|
||||
"Übungsvarianten: POST/PUT/DELETE /api/exercises/{id}/variants + reorder",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -790,6 +790,32 @@ export async function quickCreateTrainingUnit(data) {
|
|||
})
|
||||
}
|
||||
|
||||
export async function listTrainingPlanTemplates() {
|
||||
return request('/api/training-plan-templates')
|
||||
}
|
||||
|
||||
export async function getTrainingPlanTemplate(id) {
|
||||
return request(`/api/training-plan-templates/${id}`)
|
||||
}
|
||||
|
||||
export async function createTrainingPlanTemplate(data) {
|
||||
return request('/api/training-plan-templates', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateTrainingPlanTemplate(id, data) {
|
||||
return request(`/api/training-plan-templates/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteTrainingPlanTemplate(id) {
|
||||
return request(`/api/training-plan-templates/${id}`, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Version & Health
|
||||
// ============================================================================
|
||||
|
|
@ -863,6 +889,11 @@ export const api = {
|
|||
updateTrainingUnit,
|
||||
deleteTrainingUnit,
|
||||
quickCreateTrainingUnit,
|
||||
listTrainingPlanTemplates,
|
||||
getTrainingPlanTemplate,
|
||||
createTrainingPlanTemplate,
|
||||
updateTrainingPlanTemplate,
|
||||
deleteTrainingPlanTemplate,
|
||||
|
||||
// Catalogs
|
||||
listFocusAreas,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const PAGE_VERSIONS = {
|
|||
ExercisesPage: "1.1.0", // Updated: Katalog-Integration
|
||||
ClubsPage: "1.0.0",
|
||||
SkillsPage: "1.0.0",
|
||||
TrainingPlanningPage: "1.0.0",
|
||||
TrainingPlanningPage: "1.1.0",
|
||||
AdminCatalogsPage: "2.2.0", // Updated: Frontend API Calls & Field Names für renamed tables
|
||||
TrainerContextsPage: "1.0.0", // New: Trainer-Kontext-Verwaltung
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user