Numeroud bug fixes, UI improvements, small animations
Some checks failed
Automated Container Build / build-and-push (push) Failing after 3s
Some checks failed
Automated Container Build / build-and-push (push) Failing after 3s
This commit is contained in:
parent
b7ce314f01
commit
d76ec4a69f
10 changed files with 249 additions and 82 deletions
|
|
@ -121,7 +121,7 @@ export function FlashcardViewer({ cards, deckId, isShared = false, initialProgre
|
|||
function handleKeyDown(e: KeyboardEvent) {
|
||||
if (!started || completed) return;
|
||||
|
||||
if (e.key === " " || e.key === "Enter") {
|
||||
if (e.key === " " || e.key === "Enter" || e.key === "ArrowUp" || e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
setIsFlipped((prev) => {
|
||||
if (!prev) setHasFlippedOnce(true);
|
||||
|
|
@ -358,8 +358,8 @@ export function FlashcardViewer({ cards, deckId, isShared = false, initialProgre
|
|||
>
|
||||
<div
|
||||
key={currentCard.id}
|
||||
className={`relative w-full min-h-[450px] md:min-h-[550px] preserve-3d ${!swipeClass ? "transition-transform duration-500" : ""} ${
|
||||
isFlipped ? "rotate-y-180" : ""
|
||||
className={`relative w-full min-h-[450px] md:min-h-[550px] preserve-3d ${!swipeClass ? "transition-transform duration-300" : ""} ${
|
||||
isFlipped ? "rotate-x-180" : ""
|
||||
}`}
|
||||
>
|
||||
{/* Front */}
|
||||
|
|
@ -378,7 +378,7 @@ export function FlashcardViewer({ cards, deckId, isShared = false, initialProgre
|
|||
</div>
|
||||
|
||||
{/* Back */}
|
||||
<div className="absolute inset-0 backface-hidden rotate-y-180 bg-bg-surface rounded-2xl border border-border-light shadow-[var(--shadow-card)] p-8 md:p-12 flex flex-col items-center justify-center">
|
||||
<div className="absolute inset-0 backface-hidden rotate-x-180 bg-bg-surface rounded-2xl border border-border-light shadow-[var(--shadow-card)] p-8 md:p-12 flex flex-col items-center justify-center">
|
||||
<span className="absolute top-3 right-4 text-xs font-medium text-text-muted uppercase tracking-wider">
|
||||
Back
|
||||
</span>
|
||||
|
|
@ -412,35 +412,60 @@ export function FlashcardViewer({ cards, deckId, isShared = false, initialProgre
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* Grading buttons (visible after first flip) */}
|
||||
{hasFlippedOnce && (
|
||||
<div className="flex items-center justify-center gap-4 mt-6 animate-fade-in">
|
||||
<div className="relative w-full mt-6">
|
||||
{currentIndex > 0 && (
|
||||
<button
|
||||
onClick={() => gradeCard("missed")}
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-xl border-2 border-error/30 text-error font-medium hover:bg-error-bg transition-all duration-200 cursor-pointer"
|
||||
onClick={() => {
|
||||
const prevIndex = currentIndex - 1;
|
||||
setCurrentIndex(prevIndex);
|
||||
setIsFlipped(false);
|
||||
setHasFlippedOnce(false);
|
||||
|
||||
const prevId = order[prevIndex];
|
||||
const newResults = { ...results };
|
||||
delete newResults[prevId];
|
||||
setResults(newResults);
|
||||
saveProgress(order, prevIndex, newResults, mode);
|
||||
}}
|
||||
className="absolute left-0 top-0 p-2 rounded-full text-text-muted hover:bg-bg-surface-alt hover:text-text-heading transition-all duration-200 cursor-pointer z-10"
|
||||
title="Previous Card"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
||||
</svg>
|
||||
Missed
|
||||
</button>
|
||||
<button
|
||||
onClick={() => gradeCard("correct")}
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-xl border-2 border-success/30 text-success font-medium hover:bg-success-bg transition-all duration-200 cursor-pointer"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
Got It
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
|
||||
{/* Keyboard hint */}
|
||||
<div className="text-center mt-4 text-xs text-text-muted">
|
||||
{hasFlippedOnce
|
||||
? "← Missed · Got It →"
|
||||
: "Space to flip"}
|
||||
<div className="flex items-center justify-center gap-4 min-h-[52px]">
|
||||
{hasFlippedOnce && (
|
||||
<div className="flex items-center gap-4 animate-fade-in">
|
||||
<button
|
||||
onClick={() => gradeCard("missed")}
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-xl border-2 border-error/30 text-error font-medium hover:bg-error-bg transition-all duration-200 cursor-pointer"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
Missed
|
||||
</button>
|
||||
<button
|
||||
onClick={() => gradeCard("correct")}
|
||||
className="flex items-center gap-2 px-6 py-3 rounded-xl border-2 border-success/30 text-success font-medium hover:bg-success-bg transition-all duration-200 cursor-pointer"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
Got It
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-4 text-xs text-text-muted">
|
||||
{hasFlippedOnce
|
||||
? "← Missed · Got It →"
|
||||
: "Space to flip"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue