this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Separate tabs based on data completion

modamo-gh 2252e04d a867ea89

+85 -31
+59
app/library/LibraryClient.tsx
··· 1 + "use client"; 2 + 3 + import Image from "next/image"; 4 + import Link from "next/link"; 5 + import { useState } from "react"; 6 + 7 + const LibraryClient = ({ books, did }) => { 8 + const [showRankedBooks, setShowRankedBooks] = useState(true); 9 + 10 + return ( 11 + <div className="grid grid-rows-10 p-4 row-span-9"> 12 + <div className="gap-2 grid grid-cols-2 row-span-1 transition-all"> 13 + <button 14 + className={`col-span-1 flex items-center justify-center text-2xl rounded-t-2xl ${ 15 + showRankedBooks 16 + ? "bg-emerald-900 text-amber-100 transform translate-y-1" 17 + : "bg-emerald-900/80 text-amber-100/80" 18 + }`} 19 + onClick={() => setShowRankedBooks(true)} 20 + > 21 + Ranked Books 22 + </button> 23 + <button 24 + className={`col-span-1 flex items-center justify-center text-2xl rounded-t-2xl ${ 25 + !showRankedBooks 26 + ? "bg-emerald-900 text-amber-100 transform translate-y-1" 27 + : "bg-emerald-900/80 text-amber-100/80" 28 + }`} 29 + onClick={() => setShowRankedBooks(false)} 30 + > 31 + Books with Missing Data 32 + </button> 33 + </div> 34 + <div 35 + className={`auto-rows-min bg-emerald-900 gap-4 grid grid-cols-5 overflow-y-scroll p-4 rounded-b-xl row-span-9`} 36 + > 37 + {books?.map((book) => { 38 + return ( 39 + <Link 40 + href={`/book/${book.hiveID.slice(3)}`} 41 + key={book.hiveID} 42 + > 43 + <div className="aspect-2/3 overflow-hidden relative rounded-2xl hover:scale-105 transition-transform"> 44 + <Image 45 + alt={`Book cover for ${book.title} by ${book.authors}`} 46 + className="object-cover" 47 + fill 48 + src={`/api/blob?cid=${book.coverRef}&did=${did}`} 49 + /> 50 + </div> 51 + </Link> 52 + ); 53 + })} 54 + </div> 55 + </div> 56 + ); 57 + }; 58 + 59 + export default LibraryClient;
+12 -23
app/library/page.tsx
··· 1 1 import Header from "@/components/Header"; 2 2 import { getSession } from "@/lib/auth/session"; 3 3 import { Agent } from "@atproto/api"; 4 - import Image from "next/image"; 5 - import Link from "next/link"; 6 4 import { redirect } from "next/navigation"; 5 + import LibraryClient from "./LibraryClient"; 7 6 8 7 const Library = async () => { 9 8 const session = await getSession(); ··· 28 27 book.value.status === "buzz.bookhive.defs#reading" || 29 28 book.value.status === "buzz.bookhive.defs#wantToRead" 30 29 ); 30 + 31 + books = books.map((book) => ({ 32 + authors: book.value.authors, 33 + coverRef: book.value.cover.ref.toString(), 34 + hiveID: book.value.hiveId, 35 + title: book.value.title 36 + })); 31 37 } catch (error) { 32 38 console.error("Error fetching profile:", error); 33 39 ··· 38 44 return ( 39 45 <> 40 46 <Header /> 41 - <div className="auto-rows-min bg-emerald-900 gap-4 grid grid-cols-5 overflow-y-scroll p-4 rounded-2xl row-span-9"> 42 - {books?.map((book) => { 43 - return ( 44 - <Link 45 - href={`/book/${book.value.hiveId.slice(3)}`} 46 - key={book.value.hiveId} 47 - > 48 - <div className="aspect-2/3 overflow-hidden relative rounded-2xl"> 49 - <Image 50 - alt={`Book cover for ${book.value.title} by ${book.value.authors}`} 51 - className="object-cover" 52 - fill 53 - src={`/api/blob?cid=${book.value.cover?.ref?.toString()}&did=${ 54 - session.did 55 - }`} 56 - /> 57 - </div> 58 - </Link> 59 - ); 60 - })} 61 - </div> 47 + <LibraryClient 48 + books={books} 49 + did={session.did} 50 + /> 62 51 </> 63 52 ); 64 53 };
+14 -8
components/RatingInput.tsx
··· 7 7 const [value, setValue] = useState(0); 8 8 9 9 const handleSubmit = async () => { 10 - await fetch("/api/books/rating", { 11 - body: JSON.stringify({ 12 - hiveID, 13 - ratingType: url.includes("amazon") ? "amazon" : "goodreads", 14 - value 15 - }), 16 - method: "POST" 17 - }); 10 + try { 11 + const response = await fetch("/api/books/rating", { 12 + body: JSON.stringify({ 13 + hiveID, 14 + ratingType: url.includes("amazon") ? "amazon" : "goodreads", 15 + value 16 + }), 17 + method: "POST" 18 + }); 19 + 20 + if (response) { 21 + window.location.reload(); 22 + } 23 + } catch (error) {} 18 24 }; 19 25 20 26 return (