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/login): add login templates

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

+91
+40
internal/views/login/login-form.templ
··· 1 + package login 2 + 3 + templ LoginFormContent(params LoginFormParams) { 4 + <label 5 + x-init="lucide.createIcons()" 6 + if params.ErrorMessage != "" { 7 + data-field="error" 8 + } else { 9 + data-field 10 + } 11 + > 12 + Handle 13 + <input 14 + id="handle" 15 + name="handle" 16 + type="text" 17 + placeholder="username.bsky.social" 18 + autocapitalize="none" 19 + autocorrect="off" 20 + autocomplete="username" 21 + required 22 + tabindex="1" 23 + value={ params.Handle } 24 + if params.ErrorMessage != "" { 25 + aria-invalid="true" 26 + aria-errormessage="error-message" 27 + } 28 + /> 29 + if params.ErrorMessage != "" { 30 + <div id="error-message" class="error" role="status"> 31 + { params.ErrorMessage } 32 + </div> 33 + } 34 + </label> 35 + <input type="hidden" name="return_url" value={ params.ReturnUrl }/> 36 + <button type="submit" id="login-button" tabindex="2"> 37 + <i class="w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" data-lucide="loader-circle"></i> 38 + <span>Login</span> 39 + </button> 40 + }
+12
internal/views/login/login.go
··· 1 + package login 2 + 3 + type LoginPageParams struct { 4 + ReturnUrl string 5 + ErrorCode string 6 + } 7 + 8 + type LoginFormParams struct { 9 + ReturnUrl string 10 + Handle string 11 + ErrorMessage string 12 + }
+39
internal/views/login/login.templ
··· 1 + package login 2 + 3 + import "shelf.app/internal/layouts/base" 4 + 5 + templ LoginPage(params LoginPageParams) { 6 + @layouts.Base(layouts.BaseParams{Title: "login"}) { 7 + <div class="container"> 8 + <form 9 + class="group" 10 + hx-post="/login" 11 + hx-swap="innerHTML" 12 + hx-disabled-elt="#login-button" 13 + > 14 + @LoginFormContent(LoginFormParams{ 15 + ReturnUrl: params.ReturnUrl, 16 + Handle: "", 17 + ErrorMessage: "", 18 + }) 19 + </form> 20 + <div data-field="error"> 21 + if params.ErrorCode != "" { 22 + <p class="error"> 23 + switch (params.ErrorCode) { 24 + case "access_denied": 25 + You have not authorized the app. 26 + case "session": 27 + Server failed to create user session. 28 + case "handle": 29 + Server failed to validate your handle. 30 + default: 31 + Internal Server error. 32 + } 33 + Please try again. 34 + </p> 35 + } 36 + </div> 37 + </div> 38 + } 39 + }