summaryrefslogtreecommitdiff
path: root/src/components/Flashcard
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-05-21 17:13:11 +0700
committerpolwex <polwex@sortug.com>2025-05-21 17:13:11 +0700
commit7abf2227438362ad30820ee236405ec1b57a40b6 (patch)
tree41c2eb60befef7d665c8cd6feebb91cdf4536934 /src/components/Flashcard
parent9192e6c7747fd2d3f6a6c5c07d886a0982b53f11 (diff)
m
Diffstat (limited to 'src/components/Flashcard')
-rw-r--r--src/components/Flashcard/BookmarkButton.tsx41
-rw-r--r--src/components/Flashcard/Deck2.tsx29
-rw-r--r--src/components/Flashcard/ServerCard.tsx13
3 files changed, 72 insertions, 11 deletions
diff --git a/src/components/Flashcard/BookmarkButton.tsx b/src/components/Flashcard/BookmarkButton.tsx
new file mode 100644
index 0000000..5128b91
--- /dev/null
+++ b/src/components/Flashcard/BookmarkButton.tsx
@@ -0,0 +1,41 @@
+"use client";
+
+import { toggleBookmark } from "@/actions/deck";
+import { CardResponse } from "@/lib/types/cards";
+import { BookMarkedIcon, BookmarkIcon } from "lucide-react";
+import { useEffect, useState, useTransition } from "react";
+
+export const BookmarkIconito: React.FC<{ card: CardResponse }> = ({ card }) => {
+ const [notes, setNotes] = useState();
+ const [isBookmarked, setBookmarked] = useState(false);
+ useEffect(() => {
+ setBookmarked(card.expression.isBookmarked);
+ }, [card]);
+
+ const [isPending, startTransition] = useTransition();
+ const toggle = (e: React.MouseEvent) => {
+ console.log("toggling on fe");
+ e.stopPropagation();
+ startTransition(async () => {
+ const res = await toggleBookmark(
+ 2,
+ card.expression.id,
+ isBookmarked,
+ notes,
+ );
+ if ("ok" in res) setBookmarked(true);
+ });
+ };
+
+ return isBookmarked ? (
+ <BookMarkedIcon
+ onClick={toggle}
+ className="absolute top-5 right-3 hover:bg-red"
+ />
+ ) : (
+ <BookmarkIcon
+ onClick={toggle}
+ className="absolute top-5 right-3 hover:bg-red"
+ />
+ );
+};
diff --git a/src/components/Flashcard/Deck2.tsx b/src/components/Flashcard/Deck2.tsx
index 4fd8740..3194037 100644
--- a/src/components/Flashcard/Deck2.tsx
+++ b/src/components/Flashcard/Deck2.tsx
@@ -1,7 +1,13 @@
"use client";
import { CardResponse, DeckResponse } from "@/lib/types/cards";
-import React, { ReactNode, useCallback, useEffect, useState } from "react";
+import React, {
+ ReactNode,
+ useCallback,
+ useEffect,
+ useState,
+ useTransition,
+} from "react";
import { Button } from "../ui/button";
import { ChevronLeftIcon, ChevronRightIcon, RotateCcwIcon } from "lucide-react";
import "./cards.css";
@@ -39,8 +45,8 @@ function Deck({ data, cards }: { data: DeckResponse; cards: CardData[] }) {
setTimeout(() => {
setAnimationDirection("none");
setIsAnimating(false);
- }, 500); // Duration of enter animation
- }, 500); // Duration of exit animation
+ }, 200); // Duration of enter animation
+ }, 200); // Duration of exit animation
}, [currentIndex, cards.length, isAnimating]);
const handlePrev = useCallback(() => {
@@ -55,8 +61,8 @@ function Deck({ data, cards }: { data: DeckResponse; cards: CardData[] }) {
setTimeout(() => {
setAnimationDirection("none");
setIsAnimating(false);
- }, 500); // Duration of enter animation
- }, 500); // Duration of exit animation
+ }, 200); // Duration of enter animation
+ }, 200); // Duration of exit animation
}, [currentIndex, isAnimating]);
// Keyboard navigation
@@ -80,6 +86,14 @@ function Deck({ data, cards }: { data: DeckResponse; cards: CardData[] }) {
};
}, [handleNext, handlePrev, isAnimating]);
+ const [isPending, startTransition] = useTransition();
+ const shuffle = () => {
+ startTransition(async () => {
+ "use server";
+ console.log("shuffling deck...");
+ });
+ };
+
if (cards.length === 0) {
return (
<div className="min-h-screen bg-slate-50 dark:bg-slate-900 flex flex-col items-center justify-center p-4 font-inter text-slate-800 dark:text-slate-200">
@@ -93,6 +107,10 @@ function Deck({ data, cards }: { data: DeckResponse; cards: CardData[] }) {
return (
<div className="min-h-screen bg-slate-100 dark:bg-slate-900 flex flex-col items-center justify-center p-4 font-inter transition-colors duration-300">
+ <header>
+ <h1 className="text-2xl ">Deck: {data.lesson.name}</h1>
+ <p>{data.lesson.description}</p>
+ </header>
<div className="w-full max-w-md mb-8 relative">
{/* This div is for positioning the card and managing overflow during animations */}
<div className="relative h-80">
@@ -145,6 +163,7 @@ function Deck({ data, cards }: { data: DeckResponse; cards: CardData[] }) {
<div className="text-xs text-slate-500 dark:text-slate-400 mt-8">
Use Arrow Keys (← →) to navigate, Space/Enter to flip.
</div>
+ <Button onClick={shuffle}>Shuffle Deck</Button>
</div>
);
}
diff --git a/src/components/Flashcard/ServerCard.tsx b/src/components/Flashcard/ServerCard.tsx
index 75442b4..d377dce 100644
--- a/src/components/Flashcard/ServerCard.tsx
+++ b/src/components/Flashcard/ServerCard.tsx
@@ -25,11 +25,12 @@ import {
import { CardResponse } from "@/lib/types/cards";
import { thaiData } from "@/pages/api/nlp";
import { getRandomHexColor } from "@/lib/utils";
+import { BookmarkIconito } from "./BookmarkButton";
export async function CardFront({ data }: { data: CardResponse }) {
// const extraData = data.expression.lang
const extraData = await thaiData(data.expression.spelling);
- console.log({ extraData });
+ // console.log({ extraData });
return (
<div className="absolute w-full h-full bg-white dark:bg-slate-800 rounded-xl backface-hidden flex flex-col justify-center gap-8 items-center p-6">
@@ -41,10 +42,11 @@ export async function CardFront({ data }: { data: CardResponse }) {
}
>
<p className="text-5xl cursor-pointer font-semibold text-slate-800 dark:text-slate-100 text-center">
- {extraData[0]?.syllables.map((syl) => (
+ {extraData[0]?.syllables.map((syl, i) => (
<span
+ key={syl + i}
style={{ color: getRandomHexColor() }}
- className="m-1 hover:text-6l"
+ className="m-1 hover:text-6xl"
>
{syl}
</span>
@@ -92,10 +94,9 @@ export const IpaDisplay = ({
};
export async function CardBack({ data }: { data: CardResponse }) {
- // <BookmarkIcon onClick={handleClick} className="absolute top-5 right-10" />
return (
- <div className="absolute w-full h-full bg-slate-50 dark:bg-slate-700 rounded-xl backface-hidden rotate-y-180 flex flex-col justify-between items-center p-6 relative">
- <BookmarkIcon className="absolute top-5 right-10" />
+ <div className="w-full h-full bg-slate-50 dark:bg-slate-700 rounded-xl backface-hidden rotate-y-180 flex flex-col justify-between items-center p-6 relative">
+ <BookmarkIconito card={data} />
<span className="text-lg text-slate-500 dark:text-slate-400 self-start">
{data.expression.senses.map((ss, i) => (
<div key={`ss${i}`}>