BugFix bei Trainingsanzeige

This commit is contained in:
Andreas Knuth 2025-02-04 17:05:56 -06:00
parent 576689a3ed
commit f3cde1578e
3 changed files with 64 additions and 69 deletions

View File

@ -21,7 +21,9 @@
<span class="text-gray-600">({{ deck.images.length }} Pics)</span>
</div>
<div class="text-sm text-gray-600">
<div [ngClass]="{ 'text-blue-500 font-bold': isToday(getNextTrainingDate(deck)) }">Next training: {{ getNextTrainingString(deck) }}</div>
<div [ngClass]="{ 'text-blue-500 font-bold': isToday(getNextTrainingDate(deck)), 'text-rose-500 font-bold': isBeforeToday(getNextTrainingDate(deck)) }">
Next training: {{ getNextTrainingString(deck) }}
</div>
<div>Words to review: {{ getWordsToReview(deck) }}</div>
</div>
</div>
@ -97,15 +99,14 @@
</div>
</li>
</ul>
<div class="flex flex-row space-x-2">
<button (click)="openTraining(activeDeck)" class="flex-1 bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600">Start Training</button>
<div class="flex flex-row space-x-2 items-stretch">
<button (click)="openTraining(activeDeck)" class="flex-1 bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-600 flex items-center justify-center whitespace-nowrap">Start Training</button>
<div class="flex-1">
<div class="relative">
<label for="imageFile" class="flex justify-center items-center bg-green-500 text-white py-2 px-4 rounded hover:bg-green-600 cursor-pointer">
<div class="flex flex-col">
<div>Add Image</div>
<div class="text-xs">(from file)</div>
<div class="relative h-full">
<label for="imageFile" class="flex justify-center items-center bg-green-500 text-white py-2 px-4 rounded hover:bg-green-600 cursor-pointer h-full">
<div class="flex flex-col items-center">
<div class="whitespace-nowrap">Add Image</div>
<div class="text-xs whitespace-nowrap">(from file)</div>
</div>
</label>
<input #imageFile type="file" id="imageFile" (change)="onFileChange($event)" accept="image/jpeg,image/png,image/gif,image/webp" required class="hidden" />
@ -113,10 +114,10 @@
</div>
<!-- Neuer Button Paste Image -->
<div class="flex-1">
<button (click)="pasteImage()" class="w-full bg-purple-500 text-white py-2 px-4 rounded hover:bg-purple-600">
<div class="flex flex-col">
<div>Paste Image</div>
<div class="text-xs">(from clipboard)</div>
<button (click)="pasteImage()" class="w-full bg-purple-500 text-white py-2 px-4 rounded hover:bg-purple-600 flex items-center justify-center h-full">
<div class="flex flex-col items-center">
<div class="whitespace-nowrap">Paste Image</div>
<div class="text-xs whitespace-nowrap">(from clipboard)</div>
</div>
</button>
</div>

View File

@ -493,31 +493,54 @@ export class DeckListComponent implements OnInit {
}
// Methode zur Berechnung des nächsten Trainingsdatums
getNextTrainingDate(deck: Deck): Date {
const now = new Date();
now.setHours(0, 0, 0, 0);
const dueDates = deck.images.flatMap(image => image.boxes.map(box => (box.due ? new Date(box.due * 86400000) : null)));
getNextTrainingDate(deck: Deck): number {
const today = this.getTodayInDays();
const dueDates = deck.images.flatMap(image => image.boxes.map(box => (box.due ? box.due : null)));
if (dueDates.includes(null)) {
return now;
return today;
}
const futureDueDates = dueDates.filter(date => date && date >= now);
if (futureDueDates.length > 0) {
const nextDate = futureDueDates.reduce((a, b) => (a < b ? a : b));
//const futureDueDates = dueDates.filter(date => date && date >= now);
if (dueDates.length > 0) {
const nextDate = dueDates.reduce((a, b) => (a < b ? a : b));
return nextDate;
}
return now;
return today;
}
getNextTrainingString(deck: Deck): string {
return this.getNextTrainingDate(deck).toLocaleDateString();
return this.daysSinceEpochToLocalDateString(this.getNextTrainingDate(deck));
}
// In deiner Component TypeScript Datei
isToday(date: Date): boolean {
const today = new Date();
return date.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear();
isToday(epochDays: number): boolean {
return this.getTodayInDays() - epochDays === 0;
}
isBeforeToday(epochDays: number): boolean {
return this.getTodayInDays() - epochDays > 0;
}
// Methode zur Berechnung der Anzahl der zu bearbeitenden Wörter
getWordsToReview(deck: Deck): number {
const nextTraining = this.getNextTrainingDate(deck);
return deck.images.flatMap(image => image.boxes.filter(box => (box.due && new Date(box.due * 86400000) <= new Date(nextTraining)) || !box.due)).length;
// const nextTraining = this.getNextTrainingDate(deck);
// return deck.images.flatMap(image => image.boxes.filter(box => (box.due && new Date(box.due * 86400000) <= new Date(nextTraining)) || !box.due)).length;
const today = this.getTodayInDays();
return deck.images.flatMap(image => image.boxes.filter(box => (box.due && box.due <= today) || !box.due)).length;
// this.currentImageData.boxes.filter(box => box.due === undefined || box.due <= today);
}
getTodayInDays(): number {
const epoch = new Date(1970, 0, 1); // Anki uses UNIX epoch
const today = new Date();
return Math.floor((today.getTime() - epoch.getTime()) / (1000 * 60 * 60 * 24));
}
daysSinceEpochToLocalDateString(days: number): string {
const msPerDay = 24 * 60 * 60 * 1000;
// Erstelle ein Datum, das den exakten UTC-Zeitpunkt (Mitternacht UTC) repräsentiert:
const utcDate = new Date(days * msPerDay);
// Formatiere das Datum: Mit timeZone: 'UTC' wird der UTC-Wert genutzt,
// aber das Ausgabeformat (z.B. "4.2.2025" oder "2/4/2025") richtet sich nach der Locale.
return new Intl.DateTimeFormat(undefined, {
timeZone: 'UTC',
day: 'numeric',
month: 'numeric',
year: 'numeric',
}).format(utcDate);
}
}

View File

@ -1,62 +1,33 @@
<div class="mt-10">
<div class="mt-10 mx-auto max-w-5xl">
<h2 class="text-2xl font-bold mb-4">Training: {{ deck.name }}</h2>
<div class="bg-white shadow rounded-lg p-6 flex flex-col items-center">
<div class="rounded-lg p-6 flex flex-col items-center">
<canvas #canvas class="mb-4 border max-h-[50vh]"></canvas>
<div class="flex space-x-4 mb-4">
<!-- Show Button -->
<button
(click)="showText()"
class="bg-green-500 disabled:bg-green-200 text-white py-2 px-4 rounded hover:bg-green-600"
[disabled]="isShowingBox || currentBoxIndex >= boxesToReview.length"
>
Show
</button>
<button (click)="showText()" class="bg-green-500 disabled:bg-green-200 text-white py-2 px-4 rounded hover:bg-green-600" [disabled]="isShowingBox || currentBoxIndex >= boxesToReview.length">Show</button>
<!-- Again Button -->
<button
(click)="markAgain()"
class="bg-orange-500 disabled:bg-orange-200 text-white py-2 px-4 rounded hover:bg-orange-600"
[disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length"
>
<button (click)="markAgain()" class="bg-orange-500 disabled:bg-orange-200 text-white py-2 px-4 rounded hover:bg-orange-600" [disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length">
Again ({{ getNextInterval(currentBox, 'again') }})
</button>
<!-- Good Button -->
<button
(click)="markGood()"
class="bg-blue-500 disabled:bg-blue-200 text-white py-2 px-4 rounded hover:bg-blue-600"
[disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length"
>
<button (click)="markGood()" class="bg-blue-500 disabled:bg-blue-200 text-white py-2 px-4 rounded hover:bg-blue-600" [disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length">
Good ({{ getNextInterval(currentBox, 'good') }})
</button>
<!-- Easy Button -->
<button
(click)="markEasy()"
class="bg-green-500 disabled:bg-green-200 text-white py-2 px-4 rounded hover:bg-green-600"
[disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length"
>
<button (click)="markEasy()" class="bg-green-500 disabled:bg-green-200 text-white py-2 px-4 rounded hover:bg-green-600" [disabled]="!isShowingBox || currentBoxIndex >= boxesToReview.length">
Easy ({{ getNextInterval(currentBox, 'easy') }})
</button>
<!-- Next Image Button -->
<button
(click)="skipToNextImage()"
class="bg-yellow-500 disabled:bg-yellow-200 text-white py-2 px-4 rounded hover:bg-yellow-600"
[disabled]="currentImageIndex >= deck.images.length"
>
Next Image
</button>
<button (click)="skipToNextImage()" class="bg-yellow-500 disabled:bg-yellow-200 text-white py-2 px-4 rounded hover:bg-yellow-600" [disabled]="currentImageIndex >= deck.images.length">Next Image</button>
</div>
<p class="mt-2">{{ progress }}</p>
<button
(click)="closeTraining()"
class="mt-4 text-gray-500 hover:text-gray-700 underline"
>
End Training
</button>
<button (click)="closeTraining()" class="mt-4 text-gray-500 hover:text-gray-700 underline">End Training</button>
</div>
</div>
</div>