diff --git a/backend/controllers/diaryController.js b/backend/controllers/diaryController.js index 82d71fb..b2686f6 100644 --- a/backend/controllers/diaryController.js +++ b/backend/controllers/diaryController.js @@ -36,11 +36,12 @@ const updateTrainingTimes = async (req, res) => { try { const { clubId } = req.params; const { authcode: userToken } = req.headers; - const { date, trainingStart, trainingEnd } = req.body; - if (!date || !trainingStart) { + const { dateId, trainingStart, trainingEnd } = req.body; + if (!dateId || !trainingStart) { + console.log(dateId, trainingStart, trainingEnd); throw new HttpError('notallfieldsfilled', 400); } - const updatedDate = await diaryService.updateTrainingTimes(userToken, clubId, date, trainingStart, trainingEnd); + const updatedDate = await diaryService.updateTrainingTimes(userToken, clubId, dateId, trainingStart, trainingEnd); res.status(200).json(updatedDate); } catch (error) { console.error('[updateTrainingTimes] - Error:', error); diff --git a/backend/services/diaryService.js b/backend/services/diaryService.js index 8a5ed04..7136132 100644 --- a/backend/services/diaryService.js +++ b/backend/services/diaryService.js @@ -54,11 +54,11 @@ class DiaryService { return newDate; } - async updateTrainingTimes(userToken, clubId, date, trainingStart, trainingEnd) { + async updateTrainingTimes(userToken, clubId, dateId, trainingStart, trainingEnd) { console.log('[DiaryService::updateTrainingTimes] - Check user access'); await checkAccess(userToken, clubId); console.log('[DiaryService::updateTrainingTimes] - Validate date'); - const diaryDate = await DiaryDate.findOne({ where: { clubId, date } }); + const diaryDate = await DiaryDate.findOne({ where: { clubId, id: dateId } }); if (!diaryDate) { throw new HttpError('Diary entry not found', 404); } diff --git a/frontend/src/components/PDFGenerator.js b/frontend/src/components/PDFGenerator.js index 328acd8..ec04b71 100644 --- a/frontend/src/components/PDFGenerator.js +++ b/frontend/src/components/PDFGenerator.js @@ -6,8 +6,8 @@ class PDFGenerator { this.pdf = new jsPDF('p', 'mm', 'a4'); this.margin = margin; this.columnGap = columnGap; - this.pageHeight = 295 - margin * 2; // A4 height in mm minus Ränder - this.columnWidth = (210 - margin * 2 - columnGap) / 2; // Zwei Spalten mit Lücke dazwischen + this.pageHeight = 295 - margin * 2; + this.columnWidth = (210 - margin * 2 - columnGap) / 2; this.position = margin; this.yPos = this.position; this.xPos = margin; @@ -17,14 +17,12 @@ class PDFGenerator { async addSchedule(element) { const canvas = await html2canvas(element, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); - const imgWidth = 210 - this.margin * 2; // A4 width in mm minus Ränder + const imgWidth = 210 - this.margin * 2; const imgHeight = (canvas.height * imgWidth) / canvas.width; let heightLeft = imgHeight; let position = this.margin; - this.pdf.addImage(imgData, 'PNG', this.margin, position, imgWidth, imgHeight); heightLeft -= this.pageHeight; - while (heightLeft >= 0) { position = heightLeft - imgHeight + this.margin; this.pdf.addPage(); @@ -52,8 +50,6 @@ class PDFGenerator { addAddress(clubName, addressLines) { this.pdf.setFontSize(10); - - // Vereinname fett drucken this.pdf.setFont('helvetica', 'bold'); this.pdf.text(clubName, this.xPos, this.yPos); this.yPos += 5; @@ -63,30 +59,76 @@ class PDFGenerator { this.pdf.text(line, this.xPos, this.yPos); this.yPos += 5; }); - - this.yPos += 10; // Abstand zwischen den Adressen - - // Spaltenwechsel oder neuer Seite bei Bedarf + this.yPos += 10; this.checkColumnOverflow(); } checkColumnOverflow() { if (this.isLeftColumn) { if (this.yPos > this.pageHeight) { - this.xPos += this.columnWidth + this.columnGap; // Zur rechten Spalte wechseln - this.yPos = this.position; // Zurück zum Anfang der neuen Spalte + this.xPos += this.columnWidth + this.columnGap; + this.yPos = this.position; this.isLeftColumn = false; } } else { if (this.yPos > this.pageHeight) { this.pdf.addPage(); - this.xPos = this.margin; // Zurück zur linken Spalte auf der neuen Seite + this.xPos = this.margin; this.yPos = this.position; this.isLeftColumn = true; } } } + addTrainingPlan(clubName, trainingDate, trainingStart, trainingEnd, trainingPlan) { + this.pdf.setFontSize(14); + this.pdf.setFont('helvetica', 'bold'); + this.pdf.text(`${clubName} - Trainingsplan`, this.margin, this.yPos); + this.yPos += 10; + this.pdf.setFontSize(12); + this.pdf.setFont('helvetica', 'normal'); + this.pdf.text(`Datum: ${trainingDate}`, this.margin, this.yPos); + this.yPos += 7; + this.pdf.text(`Uhrzeit: ${trainingStart} - ${trainingEnd}`, this.margin, this.yPos); + this.yPos += 10; + this.pdf.setFont('helvetica', 'bold'); + this.pdf.text('Uhrzeit', this.margin, this.yPos); + this.pdf.text('Aktivität', this.margin + 60, this.yPos); + this.pdf.text('Länge / Gesamtzeit (Min)', this.margin + 150, this.yPos); + this.yPos += 10; + this.pdf.setFont('helvetica', 'normal'); + trainingPlan.forEach((item, index) => { + const time = this.calculatePlanItemTime(index, trainingStart, trainingPlan); + this.pdf.text(time, this.margin, this.yPos); + this.pdf.text(item.activity, this.margin + 60, this.yPos); + this.pdf.text(item.duration.toString(), this.margin + 150, this.yPos); + this.yPos += 7; + + if (this.yPos > this.pageHeight) { + this.addNewPage(); + } + }); + } + + calculatePlanItemTime(index, startTime, trainingPlan) { + let time = startTime; + for (let i = 0; i < index; i++) { + time = this.addDurationToTime(time, trainingPlan[i].duration); + } + return time; + } + + addDurationToTime(startTime, duration) { + let [hours, minutes] = startTime.split(':').map(Number); + minutes += Number(duration); + if (minutes >= 60) { + hours += Math.floor(minutes / 60); + minutes = minutes % 60; + } + hours = hours % 24; + return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; + } + save(filename) { this.pdf.save(filename); } diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index c30c116..b18eb5d 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -3,13 +3,14 @@

Trainingstagebuch

-
+ +

Neues Datum anlegen

@@ -28,7 +29,8 @@
-
+ +

Trainingszeiten bearbeiten

@@ -43,7 +45,7 @@
-
+

Trainingsplan

@@ -60,7 +62,7 @@ ☰ {{ calculatePlanItemTime(index) }} - {{ planItem.predefinedActivity.name }} + {{ planItem.activity }} - {{ planItem.duration }} @@ -76,7 +78,7 @@
{{ activity.name }} ({{ activity.durationText || '' }} / {{ - activity.duration }} Minuten) + activity.duration }} Minuten)
@@ -89,61 +91,7 @@ -
- -
-

Teilnehmer

-
    -
  • - -
  • -
-

Aktivitäten

- - -
    -
  • - {{ activity.description }} -
  • -
- -
-
-
- - @@ -153,33 +101,19 @@