feat(TrainingGroup): add excludeFromQuickDiaryCreate feature and update related logic
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s

- Introduced a new boolean field `excludeFromQuickDiaryCreate` in the TrainingGroup model to control group visibility in quick diary creation.
- Updated the `updateTrainingGroup` service method to handle the new field, allowing for dynamic updates based on user input.
- Enhanced the TrainingTimesTab component to include a checkbox for excluding groups from quick diary creation, improving user interaction.
- Updated localization files to include new strings related to the exclude feature, ensuring clarity in multiple languages.
- Refactored logic in DiaryView and mobile app to consider the new exclusion criteria when suggesting training slots.
This commit is contained in:
Torsten Schulz (local)
2026-05-14 22:47:02 +02:00
parent 83294406a4
commit bf3e1af084
12 changed files with 239 additions and 63 deletions

View File

@@ -32,8 +32,7 @@ export const updateTrainingGroup = async (req, res) => {
try {
const { authcode: userToken } = req.headers;
const { clubId, groupId } = req.params;
const { name, sortOrder } = req.body;
const group = await trainingGroupService.updateTrainingGroup(userToken, clubId, groupId, name, sortOrder);
const group = await trainingGroupService.updateTrainingGroup(userToken, clubId, groupId, req.body);
res.status(200).json(group);
} catch (error) {
console.error('[updateTrainingGroup] - Error:', error);

View File

@@ -0,0 +1,4 @@
-- Trainingsgruppen vom Tagebuch-Schnellanlegen ausnehmen (optional)
ALTER TABLE training_group
ADD COLUMN exclude_from_quick_diary_create TINYINT(1) NOT NULL DEFAULT 0
COMMENT '1 = Gruppe bei Schnellanlegen-Terminsuche ignorieren';

View File

@@ -38,7 +38,13 @@ const TrainingGroup = sequelize.define('TrainingGroup', {
allowNull: false,
defaultValue: 0,
comment: 'Order for displaying groups'
}
},
excludeFromQuickDiaryCreate: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
comment: 'If true, group is skipped when suggesting/creating diary dates via quick-create'
},
}, {
tableName: 'training_group',
underscored: true,

View File

@@ -159,9 +159,11 @@ class TrainingGroupService {
return group;
}
async updateTrainingGroup(userToken, clubId, groupId, name, sortOrder) {
async updateTrainingGroup(userToken, clubId, groupId, body = {}) {
await checkAccess(userToken, clubId);
const { name, sortOrder, excludeFromQuickDiaryCreate } = body;
const group = await TrainingGroup.findOne({
where: { id: groupId, clubId },
});
@@ -169,25 +171,31 @@ class TrainingGroupService {
throw new HttpError('Gruppe nicht gefunden', 404);
}
// Preset-Gruppen können nicht umbenannt werden
if (group.isPreset && name !== group.name) {
throw new HttpError('Vorgaben-Gruppen können nicht umbenannt werden', 400);
}
// Prüfe, ob bereits eine andere Gruppe mit diesem Namen existiert
if (name !== group.name) {
const existing = await TrainingGroup.findOne({
where: { clubId, name, id: { [Op.ne]: groupId } },
});
if (existing) {
throw new HttpError('Eine Gruppe mit diesem Namen existiert bereits', 409);
if (name !== undefined && name !== null) {
// Preset-Gruppen können nicht umbenannt werden
if (group.isPreset && name !== group.name) {
throw new HttpError('Vorgaben-Gruppen können nicht umbenannt werden', 400);
}
if (name !== group.name) {
const existing = await TrainingGroup.findOne({
where: { clubId, name, id: { [Op.ne]: groupId } },
});
if (existing) {
throw new HttpError('Eine Gruppe mit diesem Namen existiert bereits', 409);
}
}
group.name = name;
}
group.name = name;
if (sortOrder !== undefined) {
if (sortOrder !== undefined && sortOrder !== null) {
group.sortOrder = sortOrder;
}
if (excludeFromQuickDiaryCreate !== undefined) {
group.excludeFromQuickDiaryCreate = Boolean(excludeFromQuickDiaryCreate);
}
await group.save();
return group;
}