diff --git a/backend/controllers/memberActivityController.js b/backend/controllers/memberActivityController.js
new file mode 100644
index 0000000..337a9d0
--- /dev/null
+++ b/backend/controllers/memberActivityController.js
@@ -0,0 +1,120 @@
+import { checkAccess } from '../utils/userUtils.js';
+import DiaryMemberActivity from '../models/DiaryMemberActivity.js';
+import DiaryDateActivity from '../models/DiaryDateActivity.js';
+import DiaryDates from '../models/DiaryDates.js';
+import Participant from '../models/Participant.js';
+import PredefinedActivity from '../models/PredefinedActivity.js';
+import { Op } from 'sequelize';
+
+export const getMemberActivities = async (req, res) => {
+ try {
+ const { authcode: userToken } = req.headers;
+ const { clubId, memberId } = req.params;
+ const { period } = req.query; // 'month', '3months', '6months', 'year', 'all'
+
+ await checkAccess(userToken, clubId);
+
+ // Calculate date range based on period
+ const now = new Date();
+ let startDate = null;
+
+ switch (period) {
+ case 'month':
+ startDate = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());
+ break;
+ case '3months':
+ startDate = new Date(now.getFullYear(), now.getMonth() - 3, now.getDate());
+ break;
+ case '6months':
+ startDate = new Date(now.getFullYear(), now.getMonth() - 6, now.getDate());
+ break;
+ case 'year':
+ startDate = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate());
+ break;
+ case 'all':
+ default:
+ startDate = null;
+ break;
+ }
+
+ // Get participant ID for this member
+ const participants = await Participant.findAll({
+ where: { memberId: memberId }
+ });
+
+ if (participants.length === 0) {
+ return res.status(200).json([]);
+ }
+
+ const participantIds = participants.map(p => p.id);
+
+ // Get all diary member activities for this member
+ const whereClause = {
+ participantId: participantIds
+ };
+
+ const memberActivities = await DiaryMemberActivity.findAll({
+ where: whereClause,
+ include: [
+ {
+ model: DiaryDateActivity,
+ as: 'activity',
+ include: [
+ {
+ model: DiaryDates,
+ as: 'diaryDate',
+ where: startDate ? {
+ date: {
+ [Op.gte]: startDate
+ }
+ } : {}
+ },
+ {
+ model: PredefinedActivity,
+ as: 'predefinedActivity'
+ }
+ ]
+ }
+ ],
+ order: [[{ model: DiaryDateActivity, as: 'activity' }, { model: DiaryDates, as: 'diaryDate' }, 'date', 'DESC']]
+ });
+
+ // Group activities by name and count occurrences
+ const activityMap = new Map();
+
+ for (const ma of memberActivities) {
+ if (!ma.activity || !ma.activity.predefinedActivity) {
+ continue;
+ }
+
+ const activity = ma.activity.predefinedActivity;
+ const activityName = activity.name;
+ const date = ma.activity.diaryDate?.date;
+
+ if (!activityMap.has(activityName)) {
+ activityMap.set(activityName, {
+ name: activityName,
+ count: 0,
+ dates: []
+ });
+ }
+
+ const activityData = activityMap.get(activityName);
+ activityData.count++;
+ if (date) {
+ activityData.dates.push(date);
+ }
+ }
+
+ // Convert map to array and sort by count
+ const activities = Array.from(activityMap.values())
+ .sort((a, b) => b.count - a.count);
+
+ return res.status(200).json(activities);
+
+ } catch (error) {
+ console.error('Error fetching member activities:', error);
+ return res.status(500).json({ error: 'Failed to fetch member activities' });
+ }
+};
+
diff --git a/backend/routes/memberActivityRoutes.js b/backend/routes/memberActivityRoutes.js
new file mode 100644
index 0000000..23355fb
--- /dev/null
+++ b/backend/routes/memberActivityRoutes.js
@@ -0,0 +1,12 @@
+import express from 'express';
+import { authenticate } from '../middleware/authMiddleware.js';
+import { getMemberActivities } from '../controllers/memberActivityController.js';
+
+const router = express.Router();
+
+router.use(authenticate);
+
+router.get('/:clubId/:memberId', getMemberActivities);
+
+export default router;
+
diff --git a/backend/server.js b/backend/server.js
index ce58807..67d8805 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -38,6 +38,7 @@ import teamRoutes from './routes/teamRoutes.js';
import clubTeamRoutes from './routes/clubTeamRoutes.js';
import teamDocumentRoutes from './routes/teamDocumentRoutes.js';
import seasonRoutes from './routes/seasonRoutes.js';
+import memberActivityRoutes from './routes/memberActivityRoutes.js';
import schedulerService from './services/schedulerService.js';
const app = express();
@@ -88,6 +89,7 @@ app.use('/api/teams', teamRoutes);
app.use('/api/club-teams', clubTeamRoutes);
app.use('/api/team-documents', teamDocumentRoutes);
app.use('/api/seasons', seasonRoutes);
+app.use('/api/member-activities', memberActivityRoutes);
app.use(express.static(path.join(__dirname, '../frontend/dist')));
diff --git a/frontend/src/components/MemberActivitiesDialog.vue b/frontend/src/components/MemberActivitiesDialog.vue
new file mode 100644
index 0000000..9881c2c
--- /dev/null
+++ b/frontend/src/components/MemberActivitiesDialog.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+ Übung
+ Häufigkeit
+ Daten
+
+
+
+ {{ activity.name }}
+ {{ activity.count }}x
+
+
+