go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/chirp/pkg/controller/profile.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package controller 9 10 import ( 11 "fmt" 12 "net/http" 13 14 "go.charczuk.com/projects/chirp/pkg/config" 15 "go.charczuk.com/projects/chirp/pkg/model" 16 "go.charczuk.com/sdk/apputil" 17 "go.charczuk.com/sdk/uuid" 18 "go.charczuk.com/sdk/web" 19 ) 20 21 type Profile struct { 22 apputil.BaseController 23 24 Config config.Config 25 Model model.Manager 26 } 27 28 func (p Profile) Register(app *web.App) { 29 app.Get("/profile", web.NestMiddleware(p.profile, web.SessionRequired)) 30 app.Get("/profile/:user", web.NestMiddleware(p.profile, web.SessionRequired)) 31 app.Get("/profile/:user/:tab", web.NestMiddleware(p.profile, web.SessionRequired)) 32 app.Post("/profile.follow", web.NestMiddleware(p.profileFollow, web.SessionRequired)) 33 app.Post("/profile.unfollow", web.NestMiddleware(p.profileUnfollow, web.SessionRequired)) 34 } 35 36 type profileViewModel struct { 37 Tab string 38 User model.UserFull 39 Chirps []model.ChirpFull 40 } 41 42 func (p Profile) profile(r web.Context) web.Result { 43 sessionUserID := p.GetUserID(r) 44 var user model.UserFull 45 var err error 46 var found bool 47 if routeUsername, _ := web.RouteValue[string](r, "user"); routeUsername != "" { 48 user, found, err = p.Model.UserByUsername(r, sessionUserID, routeUsername) 49 if err != nil { 50 return r.Views().InternalError(err) 51 } 52 if !found { 53 return r.Views().NotFound() 54 } 55 } else { 56 user, found, err = p.Model.User(r, sessionUserID, sessionUserID) 57 if err != nil { 58 return r.Views().InternalError(err) 59 } 60 if !found { 61 return r.Views().NotFound() 62 } 63 } 64 65 var after *uuid.UUID 66 if queryAfter, _ := web.QueryValue[uuid.UUID](r, "after"); !queryAfter.IsZero() { 67 after = &queryAfter 68 } 69 70 tab := "posts" 71 if routeTab, _ := web.RouteValue[string](r, "tab"); routeTab != "" { 72 tab = routeTab 73 } 74 75 var chirps []model.ChirpFull 76 switch tab { 77 case "posts": 78 chirps, err = p.Model.ProfilePosts(r, sessionUserID, user.ID, DEFAULT_HOME_FEED_LENGTH, after) 79 case "replies": 80 chirps, err = p.Model.ProfileReplies(r, sessionUserID, user.ID, DEFAULT_HOME_FEED_LENGTH, after) 81 case "likes": 82 chirps, err = p.Model.ProfileLikes(r, sessionUserID, user.ID, DEFAULT_HOME_FEED_LENGTH, after) 83 default: 84 return r.Views().BadRequest(fmt.Errorf("invalid profile tab %q", tab)) 85 } 86 if err != nil { 87 return r.Views().InternalError(err) 88 } 89 if err != nil { 90 return r.Views().InternalError(err) 91 } 92 return r.Views().View("profile", profileViewModel{ 93 Tab: tab, 94 User: user, 95 Chirps: chirps, 96 }) 97 } 98 99 func (p Profile) profileFollow(r web.Context) web.Result { 100 sessionUserID := p.GetUserID(r) 101 targetUserID, err := web.FormValue[uuid.UUID](r, "id") 102 if err != nil { 103 return r.Views().BadRequest(err) 104 } 105 targetUser, found, err := p.Model.User(r, sessionUserID, targetUserID) 106 if err != nil { 107 return r.Views().InternalError(err) 108 } 109 if !found { 110 return r.Views().NotFound() 111 } 112 113 if err = p.Model.Follow(r, sessionUserID, targetUserID); err != nil { 114 return r.Views().InternalError(err) 115 } 116 return web.RedirectWithMethodf(http.MethodGet, "/profile/%s", targetUser.Email) 117 } 118 119 func (p Profile) profileUnfollow(r web.Context) web.Result { 120 sessionUserID := p.GetUserID(r) 121 targetUserID, err := web.FormValue[uuid.UUID](r, "id") 122 if err != nil { 123 return r.Views().BadRequest(err) 124 } 125 _, found, err := p.Model.User(r, sessionUserID, targetUserID) 126 if err != nil { 127 return r.Views().InternalError(err) 128 } 129 if !found { 130 return r.Views().NotFound() 131 } 132 if err = p.Model.Unfollow(r, sessionUserID, targetUserID); err != nil { 133 return r.Views().InternalError(err) 134 } 135 return web.RedirectWithMethodf(http.MethodGet, "/home") 136 }