feat(ParticipantController, ParticipantModel, ParticipantRoutes, DiaryParticipantsPanel, i18n): implement participant status management and UI updates
- Added functionality to update participant attendance status, allowing for 'excused' and 'cancelled' states. - Enhanced the participant model to include a default attendance status and validation for status values. - Updated participant routes to support status updates and integrated new status handling in the participant controller. - Modified the DiaryParticipantsPanel to visually indicate participant status and added a toggle for changing status. - Expanded localization files to include new keys for participant status, improving accessibility for users in both English and German.
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
import Participant from '../models/Participant.js';
|
||||
import DiaryDates from '../models/DiaryDates.js';
|
||||
import DiaryMemberActivity from '../models/DiaryMemberActivity.js';
|
||||
import { devLog } from '../utils/logger.js';
|
||||
import { emitParticipantAdded, emitParticipantRemoved, emitParticipantUpdated } from '../services/socketService.js';
|
||||
|
||||
const PARTICIPANT_ATTRIBUTES = ['id', 'diaryDateId', 'memberId', 'attendanceStatus', 'groupId', 'notes', 'createdAt', 'updatedAt'];
|
||||
|
||||
export const getParticipants = async (req, res) => {
|
||||
try {
|
||||
const { dateId } = req.params;
|
||||
const participants = await Participant.findAll({
|
||||
where: { diaryDateId: dateId },
|
||||
attributes: ['id', 'diaryDateId', 'memberId', 'groupId', 'notes', 'createdAt', 'updatedAt']
|
||||
attributes: PARTICIPANT_ATTRIBUTES
|
||||
});
|
||||
res.status(200).json(participants);
|
||||
} catch (error) {
|
||||
@@ -68,12 +72,22 @@ export const updateParticipantGroup = async (req, res) => {
|
||||
export const addParticipant = async (req, res) => {
|
||||
try {
|
||||
const { diaryDateId, memberId } = req.body;
|
||||
const participant = await Participant.create({ diaryDateId, memberId });
|
||||
const [participant, created] = await Participant.findOrCreate({
|
||||
where: { diaryDateId, memberId },
|
||||
defaults: { diaryDateId, memberId, attendanceStatus: 'present' }
|
||||
});
|
||||
|
||||
participant.attendanceStatus = 'present';
|
||||
await participant.save();
|
||||
|
||||
// Hole DiaryDate für clubId
|
||||
const diaryDate = await DiaryDates.findByPk(diaryDateId);
|
||||
if (diaryDate?.clubId) {
|
||||
emitParticipantAdded(diaryDate.clubId, diaryDateId, participant);
|
||||
if (created) {
|
||||
emitParticipantAdded(diaryDate.clubId, diaryDateId, participant);
|
||||
} else {
|
||||
emitParticipantUpdated(diaryDate.clubId, diaryDateId, participant);
|
||||
}
|
||||
}
|
||||
|
||||
res.status(201).json(participant);
|
||||
@@ -90,6 +104,15 @@ export const removeParticipant = async (req, res) => {
|
||||
// Hole DiaryDate für clubId vor dem Löschen
|
||||
const diaryDate = await DiaryDates.findByPk(diaryDateId);
|
||||
const clubId = diaryDate?.clubId;
|
||||
|
||||
const participant = await Participant.findOne({
|
||||
where: { diaryDateId, memberId },
|
||||
attributes: ['id']
|
||||
});
|
||||
|
||||
if (participant) {
|
||||
await DiaryMemberActivity.destroy({ where: { participantId: participant.id } });
|
||||
}
|
||||
|
||||
await Participant.destroy({ where: { diaryDateId, memberId } });
|
||||
|
||||
@@ -104,3 +127,53 @@ export const removeParticipant = async (req, res) => {
|
||||
res.status(500).json({ error: 'Fehler beim Entfernen des Teilnehmers' });
|
||||
}
|
||||
};
|
||||
|
||||
export const updateParticipantStatus = async (req, res) => {
|
||||
try {
|
||||
const { dateId, memberId } = req.params;
|
||||
const { attendanceStatus } = req.body;
|
||||
|
||||
if (!['excused', 'cancelled'].includes(attendanceStatus)) {
|
||||
return res.status(400).json({ error: 'Ungültiger Teilnehmerstatus' });
|
||||
}
|
||||
|
||||
const diaryDate = await DiaryDates.findByPk(dateId);
|
||||
if (!diaryDate) {
|
||||
return res.status(404).json({ error: 'Trainingstag nicht gefunden' });
|
||||
}
|
||||
|
||||
const [participant] = await Participant.findOrCreate({
|
||||
where: {
|
||||
diaryDateId: dateId,
|
||||
memberId
|
||||
},
|
||||
defaults: {
|
||||
diaryDateId: dateId,
|
||||
memberId,
|
||||
attendanceStatus
|
||||
}
|
||||
});
|
||||
|
||||
participant.attendanceStatus = attendanceStatus;
|
||||
participant.groupId = null;
|
||||
await participant.save();
|
||||
await DiaryMemberActivity.destroy({ where: { participantId: participant.id } });
|
||||
|
||||
const updatedParticipant = await Participant.findOne({
|
||||
where: {
|
||||
diaryDateId: dateId,
|
||||
memberId
|
||||
},
|
||||
attributes: PARTICIPANT_ATTRIBUTES
|
||||
});
|
||||
|
||||
if (diaryDate.clubId && updatedParticipant) {
|
||||
emitParticipantUpdated(diaryDate.clubId, dateId, updatedParticipant);
|
||||
}
|
||||
|
||||
res.status(200).json(updatedParticipant || participant);
|
||||
} catch (error) {
|
||||
devLog(error);
|
||||
res.status(500).json({ error: 'Fehler beim Aktualisieren des Teilnehmerstatus' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,6 +28,14 @@ const Participant = sequelize.define('Participant', {
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
attendanceStatus: {
|
||||
type: DataTypes.STRING(32),
|
||||
allowNull: false,
|
||||
defaultValue: 'present',
|
||||
validate: {
|
||||
isIn: [['present', 'excused', 'cancelled']]
|
||||
}
|
||||
},
|
||||
groupId: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import express from 'express';
|
||||
import { getParticipants, addParticipant, removeParticipant, updateParticipantGroup } from '../controllers/participantController.js';
|
||||
import { getParticipants, addParticipant, removeParticipant, updateParticipantGroup, updateParticipantStatus } from '../controllers/participantController.js';
|
||||
import { authenticate } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = express.Router();
|
||||
@@ -7,6 +7,7 @@ const router = express.Router();
|
||||
router.get('/:dateId', authenticate, getParticipants);
|
||||
router.post('/add', authenticate, addParticipant);
|
||||
router.post('/remove', authenticate, removeParticipant);
|
||||
router.put('/:dateId/:memberId/status', authenticate, updateParticipantStatus);
|
||||
router.put('/:dateId/:memberId/group', authenticate, updateParticipantGroup);
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user