Files
deckyvault/components/saved-games/bookmark-button.tsx
T
adrianbonpin b0688f8f2a Refactor: Remove server state files and update server log handling
- Deleted server-stopped, server.log, and server.pid files to clean up unused state.
- Updated game-page-client.tsx to enhance button accessibility with cursor-pointer class.
- Modified not-found.tsx, page.tsx, and profile/page.tsx for consistent cursor-pointer usage on links.
- Adjusted search/page.tsx and components/auth/*.tsx for improved button interactions with cursor-pointer.
- Refined navbar.tsx for better user experience with cursor-pointer on navigation links.
- Updated settings-security-tab.tsx for passkey management API endpoints and improved error handling.
- Enhanced saved-games components for better user interaction with cursor-pointer on buttons.
- General code cleanup and consistency improvements across various components.
2026-04-26 12:09:37 -05:00

108 lines
2.8 KiB
TypeScript

"use client"
import { useState, useEffect } from "react"
import { Bookmark, Loader2 } from "lucide-react"
import { motion, AnimatePresence } from "motion/react"
import { useSession } from "@/lib/auth-client"
interface BookmarkButtonProps {
gameId: string
className?: string
}
export function BookmarkButton({ gameId, className = "" }: BookmarkButtonProps) {
const { data: session } = useSession()
const [isSaved, setIsSaved] = useState(false)
const [isLoading, setIsLoading] = useState(true)
const [isToggling, setIsToggling] = useState(false)
useEffect(() => {
if (!session) {
setIsLoading(false)
return
}
async function checkSaved() {
try {
const res = await fetch(`/api/user/me/saved-games/check/${gameId}`)
if (res.ok) {
const data = await res.json()
setIsSaved(data.saved)
}
} catch (err) {
console.error("Failed to check saved status:", err)
} finally {
setIsLoading(false)
}
}
checkSaved()
}, [session, gameId])
const toggleSave = async () => {
if (!session || isToggling) return
setIsToggling(true)
try {
if (isSaved) {
const res = await fetch(`/api/user/me/saved-games/${gameId}`, {
method: "DELETE",
})
if (res.ok) {
setIsSaved(false)
}
} else {
const res = await fetch("/api/user/me/saved-games", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ gameId }),
})
if (res.ok) {
setIsSaved(true)
}
}
} catch (err) {
console.error("Failed to toggle saved game:", err)
} finally {
setIsToggling(false)
}
}
if (!session || isLoading) {
return null
}
return (
<motion.button
whileTap={{ scale: 0.9 }}
onClick={toggleSave}
disabled={isToggling}
className={`flex items-center gap-2 px-3 py-2 rounded-lg border transition-colors cursor-pointer ${
isSaved
? "bg-primary/10 border-primary/30 text-primary"
: "bg-text/5 border-border text-text/50 hover:text-text hover:border-primary/30"
} ${className}`}
>
<AnimatePresence mode="wait">
{isToggling ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<motion.div
key={isSaved ? "saved" : "not-saved"}
initial={{ scale: 0.8 }}
animate={{ scale: 1 }}
exit={{ scale: 0.8 }}
>
<Bookmark
className={`h-4 w-4 ${isSaved ? "fill-primary" : ""}`}
/>
</motion.div>
)}
</AnimatePresence>
<span className="text-sm font-medium">
{isSaved ? "Saved" : "Save"}
</span>
</motion.button>
)
}