diff options
author | polwex <polwex@sortug.com> | 2025-05-21 17:13:11 +0700 |
---|---|---|
committer | polwex <polwex@sortug.com> | 2025-05-21 17:13:11 +0700 |
commit | 7abf2227438362ad30820ee236405ec1b57a40b6 (patch) | |
tree | 41c2eb60befef7d665c8cd6feebb91cdf4536934 /src/components/Flashcard | |
parent | 9192e6c7747fd2d3f6a6c5c07d886a0982b53f11 (diff) |
m
Diffstat (limited to 'src/components/Flashcard')
-rw-r--r-- | src/components/Flashcard/BookmarkButton.tsx | 41 | ||||
-rw-r--r-- | src/components/Flashcard/Deck2.tsx | 29 | ||||
-rw-r--r-- | src/components/Flashcard/ServerCard.tsx | 13 |
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}`}> |