this repo has no description
1
fork

Configure Feed

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

Update book page count if none is retrieved

modamo-gh 52f23e98 d7b363b8

+185 -15
+36
app/api/books/pageCount/route.ts
··· 1 + import { supabase } from "@/lib/supabase/server"; 2 + import { NextRequest, NextResponse } from "next/server"; 3 + 4 + export async function POST(request: NextRequest) { 5 + try { 6 + const body = await request.json(); 7 + const { authors, hiveID, title, value } = body; 8 + 9 + if (!hiveID || !value) { 10 + return NextResponse.json( 11 + { error: "Missing hiveId or value" }, 12 + { status: 400 } 13 + ); 14 + } 15 + 16 + const { error, count } = await supabase.from("books").upsert({ 17 + authors, 18 + hive_id: hiveID, 19 + page_count: Number(value), 20 + title 21 + }); 22 + 23 + if (error) { 24 + return NextResponse.json({ error: error.message }, { status: 500 }); 25 + } 26 + 27 + return NextResponse.json({ success: true }); 28 + } catch (error) { 29 + console.error(error); 30 + 31 + return NextResponse.json( 32 + { error: "Unexpected error" }, 33 + { status: 500 } 34 + ); 35 + } 36 + }
+23 -5
app/book/[bookID]/page.tsx
··· 1 1 import Header from "@/components/Header"; 2 + import PageCountInput from "@/components/PageCountInput"; 2 3 import RatingInput from "@/components/RatingInput"; 3 4 import { getSession } from "@/lib/auth/session"; 4 5 import { getBookMeta } from "@/lib/books/meta"; ··· 35 36 book?.value.hiveId, 36 37 book?.value.title 37 38 ); 39 + 40 + console.log(book, meta); 38 41 } catch (error) { 39 42 console.error("Error fetching book:", error); 40 43 } ··· 84 87 </h2> 85 88 </div> 86 89 <div className="flex items-center justify-center row-span-4"> 87 - <p className="text-center text-xl text-emerald-900"> 88 - {meta.page_count} 89 - </p> 90 + {meta.page_count ? ( 91 + <p className="text-center text-xl text-emerald-900"> 92 + {meta.page_count} 93 + </p> 94 + ) : ( 95 + <PageCountInput 96 + authors={book?.value.authors} 97 + hiveID={book?.value.hiveId} 98 + title={book?.value.title} 99 + url={urls.goodreads} 100 + /> 101 + )} 90 102 </div> 91 103 </div> 92 104 <div className="bg-amber-100 grid grid-rows-5 p-4 rounded-2xl"> ··· 101 113 {meta.amazon_rating} 102 114 </p> 103 115 ) : ( 104 - <RatingInput hiveID={book?.value.hiveId} url={urls.amazon} /> 116 + <RatingInput 117 + hiveID={book?.value.hiveId} 118 + url={urls.amazon} 119 + /> 105 120 )} 106 121 </div> 107 122 </div> ··· 117 132 {meta.goodreads_rating} 118 133 </p> 119 134 ) : ( 120 - <RatingInput hiveID={book?.value.hiveId} url={urls.goodreads} /> 135 + <RatingInput 136 + hiveID={book?.value.hiveId} 137 + url={urls.goodreads} 138 + /> 121 139 )} 122 140 </div> 123 141 </div>
+29 -1
app/library/LibraryClient.tsx
··· 5 5 import { useState } from "react"; 6 6 7 7 const LibraryClient = ({ did, incompleteBooks, rankedBooks }) => { 8 + let maxRating = -Infinity; 9 + let minRating = Infinity; 10 + 11 + rankedBooks.forEach((book) => { 12 + maxRating = Math.max(book.averageRating, maxRating); 13 + minRating = Math.min(book.averageRating, minRating); 14 + }); 15 + 16 + rankedBooks = rankedBooks 17 + .map((book) => ({ 18 + ...book, 19 + normalizedRating: 20 + (100 * (book.averageRating - minRating)) / 21 + (maxRating - minRating) 22 + })) 23 + .map((book) => ({ 24 + ...book, 25 + hrsToRead: (275 * book.pageCount) / 60 / 250 26 + })) 27 + .map((book) => ({ 28 + ...book, 29 + eph: book.normalizedRating / book.hrsToRead 30 + })); 31 + 32 + rankedBooks.sort((a, b) => b.eph - a.eph); 33 + 34 + console.log(rankedBooks); 35 + 36 + const [displayedBooks, setDisplayedBooks] = useState(rankedBooks); 8 37 const [showRankedBooks, setShowRankedBooks] = useState(true); 9 - const [displayedBooks, setDisplayedBooks] = useState(); 10 38 11 39 return ( 12 40 <div className="grid grid-rows-10 p-4 row-span-9">
+17 -4
app/library/page.tsx
··· 46 46 books.map((book) => book.hiveID) 47 47 ); 48 48 49 - rankedBooks = books.filter((book) => { 50 - const meta = data?.find((m) => m.hive_id === book.hiveID); 49 + rankedBooks = books 50 + .filter((book) => { 51 + const meta = data?.find((m) => m.hive_id === book.hiveID); 52 + 53 + return meta && meta.amazon_rating && meta.goodreads_rating; 54 + }) 55 + .map((book) => { 56 + const meta = data?.find((m) => m.hive_id === book.hiveID); 51 57 52 - return meta && meta.amazon_rating && meta.goodreads_rating; 53 - }); 58 + return { 59 + ...book, 60 + averageRating: 61 + (100 * 62 + ((meta.amazon_rating + meta.goodreads_rating) / 63 + 2)) / 64 + 5, pageCount: meta.page_count 65 + }; 66 + }); 54 67 incompleteBooks = books.filter((book) => { 55 68 const meta = data?.find((m) => m.hive_id === book.hiveID); 56 69
+56
components/PageCountInput.tsx
··· 1 + "use client"; 2 + 3 + import Link from "next/link"; 4 + import { useState } from "react"; 5 + 6 + const PageCountInput = ({authors, hiveID, title, url }) => { 7 + const [value, setValue] = useState(0); 8 + 9 + const handleSubmit = async () => { 10 + try { 11 + const response = await fetch("/api/books/pageCount", { 12 + body: JSON.stringify({ 13 + authors, 14 + hiveID, 15 + title, 16 + value 17 + }), 18 + method: "POST" 19 + }); 20 + 21 + if (response) { 22 + window.location.reload(); 23 + } 24 + } catch (error) {} 25 + }; 26 + 27 + return ( 28 + <div className="flex flex-col gap-4"> 29 + <input 30 + className="border-2 border-emerald-900 h-12 px-4 py-2 rounded-lg text-emerald-900" 31 + min={0} 32 + name="" 33 + onChange={(e) => setValue(Number(e.currentTarget.value))} 34 + placeholder="Add Page Count" 35 + step={1} 36 + type="number" 37 + value={value} 38 + /> 39 + <button 40 + className="active:bg-emerald-800 bg-emerald-900 hover:cursor-pointer flex items-center justify-center h-12 px-4 py-2 text-amber-100 rounded-lg" 41 + onClick={handleSubmit} 42 + > 43 + Submit 44 + </button> 45 + <Link 46 + className="bg-emerald-900 h-12 px-4 py-2 rounded-lg text-amber-100 text-center" 47 + href={url} 48 + target="_blank" 49 + > 50 + Goodreads Search Results 51 + </Link> 52 + </div> 53 + ); 54 + }; 55 + 56 + export default PageCountInput;
+24 -5
lib/books/google.ts
··· 1 + import { it } from "node:test"; 1 2 import { supabase } from "../supabase/server"; 2 3 3 4 export const fetchNumberOfPages = async ( ··· 13 14 14 15 if (existing?.page_count) { 15 16 return existing.page_count; 16 - } else { 17 - console.log("Nada"); 18 17 } 19 18 20 19 try { ··· 25 24 process.env.GOOGLE_BOOKS_API_KEY 26 25 }&maxResults=1` 27 26 ); 27 + 28 + 29 + 30 + if(!response){ 31 + return; 32 + } 33 + 28 34 const json = await response.json(); 29 - const item = json.items?.[0]; 30 - const volumeInfo = item.volumeInfo; 35 + 36 + console.log(json) 37 + if(!json){ 38 + return; 39 + } 31 40 32 - console.log(volumeInfo); 41 + const item = json.items; 33 42 43 + if(!item){ 44 + return; 45 + } 46 + 47 + const volumeInfo = item.volumeInfo || item[0].volumeInfo; 48 + 49 + if(!volumeInfo || !volumeInfo.pageCount){ 50 + return; 51 + } 52 + 34 53 const { data, error: e } = await supabase.from("books").upsert( 35 54 { 36 55 authors,