Discover books, shows, and movies at your level. Track your progress by filling your Shelf with what you find, and share with other language learners. *No dusting required. shlf.space

feat(views): add 'my books' page

Signed-off-by: brookjeynes <me@brookjeynes.dev>

authored by brookjeynes.dev and committed by tangled.org c26a2ac4 c03e576c

+112 -4
+8
internal/components/book/book.go
··· 1 + package book 2 + 3 + type BookParams struct { 4 + Yes24Id string 5 + Title string 6 + Author string 7 + Description string 8 + }
+34
internal/components/book/book.templ
··· 1 + package book 2 + 3 + import "fmt" 4 + 5 + templ Book(params BookParams) { 6 + <style> 7 + .hide { 8 + display: none; 9 + } 10 + .book:hover + .hide { 11 + display: block; 12 + } 13 + </style> 14 + <div class="relative inline-block"> 15 + <img 16 + alt={ fmt.Sprintf("%s's spine", params.Title) } 17 + src={ templ.SafeURL(fmt.Sprintf("https://image.yes24.com/goods/%s/SIDE/XL", params.Yes24Id)) } 18 + class="book w-6" 19 + /> 20 + <div class="hide absolute top-10 left-5 border bg-white z-10"> 21 + <div class="flex gap-2 w-96"> 22 + <div class="w-3/4"> 23 + <h2>{ params.Title }</h2> 24 + <h4>By { params.Author }</h4> 25 + <p>{ params.Description }</p> 26 + </div> 27 + <img 28 + class="w-1/4 h-fit" 29 + src={ templ.SafeURL(fmt.Sprintf("https://image.yes24.com/goods/%s/XL", params.Yes24Id)) } 30 + /> 31 + </div> 32 + </div> 33 + </div> 34 + }
+1 -1
internal/components/header/header.go
··· 1 - package components 1 + package header 2 2 3 3 import "shlf.space/internal/server/oauth" 4 4
+2 -2
internal/components/header/header.templ
··· 1 - package components 1 + package header 2 2 3 3 import "fmt" 4 4 ··· 36 36 <div class="absolute flex flex-col right-0 mt-2 p-1 gap-1 w-48 bg-white drop-shadow-sm"> 37 37 <button 38 38 type="button" 39 - onclick="localStorage.setItem('shlf-language', 'ko');" 39 + @click="localStorage.setItem('shlf-language', 'ko');" 40 40 hx-swap="none" 41 41 class="button border-none text-sm w-full" 42 42 >
+15
internal/server/my-books.go
··· 1 + package server 2 + 3 + import ( 4 + "net/http" 5 + 6 + mybooks "shlf.space/internal/views/my-books" 7 + ) 8 + 9 + func (s *Server) MyBooks(w http.ResponseWriter, r *http.Request) { 10 + user := s.oauth.GetAccountUser(r) 11 + 12 + mybooks.MyBooksPage(mybooks.MyBooksParams{ 13 + User: user, 14 + }).Render(r.Context(), w) 15 + }
+1
internal/server/router.go
··· 72 72 router := chi.NewRouter() 73 73 74 74 router.With(middleware.ResolveIdent()).Route("/{user}", func(r chi.Router) { 75 + r.Get("/books", s.MyBooks) 75 76 }) 76 77 77 78 router.NotFound(func(w http.ResponseWriter, r *http.Request) {
+1 -1
internal/views/index/index.templ
··· 5 5 6 6 templ IndexPage(params IndexPageParams) { 7 7 @layouts.Base(layouts.BaseParams{Title: "home"}) { 8 - @components.Header(components.HeaderParams{User: params.User}) 8 + @header.Header(header.HeaderParams{User: params.User}) 9 9 <div></div> 10 10 } 11 11 }
+7
internal/views/my-books/my-books.go
··· 1 + package mybooks 2 + 3 + import "shlf.space/internal/server/oauth" 4 + 5 + type MyBooksParams struct { 6 + User *oauth.AccountUser 7 + }
+43
internal/views/my-books/my-books.templ
··· 1 + package mybooks 2 + 3 + import ( 4 + "fmt" 5 + "shlf.space/internal/components/book" 6 + "shlf.space/internal/components/header" 7 + "shlf.space/internal/layouts/base" 8 + ) 9 + 10 + templ MyBooksPage(params MyBooksParams) { 11 + <style> 12 + .add-book { 13 + writing-mode: vertical-rl; 14 + text-orientation: upright; 15 + } 16 + </style> 17 + @layouts.Base(layouts.BaseParams{Title: fmt.Sprintf("%s's books", params.User.Account.Handle)}) { 18 + @header.Header(header.HeaderParams{User: params.User}) 19 + <div class="container"> 20 + <div id="book-row-1" class="flex items-end"> 21 + @book.Book(book.BookParams{ 22 + Yes24Id: "124807552", 23 + Title: "메멘과 모리", 24 + Author: "요시타케 신스케", 25 + Description: "‘사람은 무엇을 위해 살아가는가?’, ‘살아가는 의미와 목적이 필요한가?’에 대한 정답 없는 고민으로 괴로운 당신에게 요시타케 신스케가 전하는 세 가지 이야기. ", 26 + }) 27 + @book.Book(book.BookParams{ 28 + Yes24Id: "58552371", 29 + Title: "세계를 건너 너에게 갈게", 30 + Author: "이꽃님", 31 + Description: "“나에게. 아빠가 쓰라고 해서 쓰는 거야.” 첫 문장으로 시작한 편지가 “세계를 건너 너에게 갈게.”라는 마지막 문장에 닿기까지, 두 사람의 진심이 하나의 진실을 향해 가는 동안 쌓아올린 감동은 많은 독자들에게 울음을 울게 만들었다.", 32 + }) 33 + <a 34 + href="/browse" 35 + class="flex flex-col items-center justify-between gap-10 py-2 border border-dashed" 36 + > 37 + <i class="w-4 h-4" data-lucide="plus"></i> 38 + <span class="uppercase text-sm add-book">add book</span> 39 + </a> 40 + </div> 41 + </div> 42 + } 43 + }