(UI/STYLE): Created a simple UI for the profile page. #2
@ -46,7 +46,12 @@ func GoogleCallback(ctx *gin.Context) {
|
|||||||
false, // TODO: True in prod
|
false, // TODO: True in prod
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
ctx.JSON(http.StatusOK, gin.H{"jwt": jwt, "googleUserInfo": googleUserInfo, "dbUser": dbUser})
|
|
||||||
|
// ctx.JSON(http.StatusOK, gin.H{"jwt": jwt, "googleUserInfo": googleUserInfo, "dbUser": dbUser})
|
||||||
|
_ = dbUser
|
||||||
|
_ = googleUserInfo
|
||||||
|
|
||||||
|
ctx.Redirect(http.StatusSeeOther, "/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
||||||
layouts "github.com/haydenhargreaves/Potion/internal/templates/layouts"
|
layouts "github.com/haydenhargreaves/Potion/internal/templates/layouts"
|
||||||
pages "github.com/haydenhargreaves/Potion/internal/templates/pages"
|
pages "github.com/haydenhargreaves/Potion/internal/templates/pages"
|
||||||
)
|
)
|
||||||
@ -35,8 +38,18 @@ func CreatePage(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ProfilePage(ctx *gin.Context) {
|
func ProfilePage(ctx *gin.Context) {
|
||||||
|
// If not logged in, direct to the login page
|
||||||
|
if !domain.IsLoggedIn(ctx) {
|
||||||
|
ctx.Redirect(http.StatusSeeOther, "/v1/web/login")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else, get the user data
|
||||||
|
deps := ctx.MustGet("deps").(*domain.InjectedDependencies)
|
||||||
|
user := deps.UserService.GetAuthenicatedUser(ctx)
|
||||||
|
|
||||||
title := "Potion - Profile"
|
title := "Potion - Profile"
|
||||||
page := pages.ProfilePage()
|
page := pages.ProfilePage(user)
|
||||||
|
|
||||||
ctx.HTML(200, "", layouts.AppLayout(title, page))
|
ctx.HTML(200, "", layouts.AppLayout(title, page))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import domain "github.com/haydenhargreaves/Potion/internal/domain/user"
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
domain "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||||
|
)
|
||||||
|
|
||||||
// UserService implements the domain.UserService defined in the domain module.
|
// UserService implements the domain.UserService defined in the domain module.
|
||||||
type UserService struct {
|
type UserService struct {
|
||||||
@ -15,3 +18,18 @@ var _ domain.UserService = (*UserService)(nil)
|
|||||||
func NewUserService(userRepository domain.UserRepository) domain.UserService {
|
func NewUserService(userRepository domain.UserRepository) domain.UserService {
|
||||||
return &UserService{userRepository: userRepository}
|
return &UserService{userRepository: userRepository}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *UserService) GetAuthenicatedUser(ctx *gin.Context) domain.User {
|
||||||
|
val, ok := ctx.Get("userId")
|
||||||
|
if !ok {
|
||||||
|
return domain.User{}
|
||||||
|
}
|
||||||
|
|
||||||
|
id := val.(int)
|
||||||
|
user, err := s.userRepository.GetUserById(id)
|
||||||
|
if err != nil {
|
||||||
|
return domain.User{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *user
|
||||||
|
}
|
||||||
|
|||||||
@ -3,4 +3,5 @@ package domain
|
|||||||
type UserRepository interface {
|
type UserRepository interface {
|
||||||
CreateGoogleUser(googleUserInfo *GoogleUserInfo, googleRefreshToken string) (User, error)
|
CreateGoogleUser(googleUserInfo *GoogleUserInfo, googleRefreshToken string) (User, error)
|
||||||
GetGoogleUser(googleId string) (*User, error)
|
GetGoogleUser(googleId string) (*User, error)
|
||||||
|
GetUserById(id int) (*User, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
type UserService interface {
|
type UserService interface {
|
||||||
|
GetAuthenicatedUser(ctx *gin.Context) User
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,3 +105,39 @@ func (r *UserRepository) GetGoogleUser(googleId string) (*domain.User, error) {
|
|||||||
|
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *UserRepository) GetUserById(id int) (*domain.User, error) {
|
||||||
|
tx, err := r.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var user domain.User
|
||||||
|
query := `SELECT * FROM users WHERE id = $1`
|
||||||
|
|
||||||
|
if err := tx.QueryRow(query, id).Scan(
|
||||||
|
&user.Id,
|
||||||
|
&user.GoogleId,
|
||||||
|
&user.Name,
|
||||||
|
&user.Email,
|
||||||
|
&user.ImageUrl,
|
||||||
|
&user.GoogleRefreshToken,
|
||||||
|
&user.Created,
|
||||||
|
); err != nil {
|
||||||
|
// If no user was found, don't error, just return
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &user, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -1,38 +1,37 @@
|
|||||||
package templates
|
package templates
|
||||||
|
|
||||||
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
||||||
|
import "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||||
|
|
||||||
templ userDetailsSection(name, email, url string) {
|
templ userDetailsSection(user domain.User) {
|
||||||
<section class="w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300">
|
<section class="w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300">
|
||||||
<div class="w-full p-4 md:p-8 flex items-center gap-x-8">
|
<div class="w-full p-4 md:p-8 flex items-center gap-x-8">
|
||||||
<img class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none" src={ url }/>
|
<img class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none" src={
|
||||||
<div class="">
|
user.ImageUrl } />
|
||||||
<h1 class="text-md md:text-2xl font-semibold">{ name }</h1>
|
<div class="">
|
||||||
<p class="text-xs md:text-sm">{ email }</p>
|
<h1 class="text-md md:text-2xl font-semibold">{ user.Name }</h1>
|
||||||
</div>
|
<p class="text-xs md:text-sm">{ user.Email }</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ logoutSection() {
|
templ logoutSection() {
|
||||||
<section class="w-full flex flex-col justify-center items-center py-8 border-t border-gray-300">
|
<section class="w-full flex flex-col justify-center items-center py-8 border-t border-gray-300">
|
||||||
<button
|
<button
|
||||||
class="border border-red-500 text-red-500 w-9/10 md:w-1/3 py-2 rounded-lg hover:cursor-pointer hover:bg-red-100 duration-300"
|
class="border border-red-500 text-red-500 w-9/10 md:w-1/3 py-2 rounded-lg hover:cursor-pointer hover:bg-red-100 duration-300">
|
||||||
>
|
Logout
|
||||||
Logout
|
</button>
|
||||||
</button>
|
</section>
|
||||||
</section>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templ ProfilePage() {
|
templ ProfilePage(user domain.User) {
|
||||||
@components.Navbar(" profile")
|
@components.Navbar(" profile")
|
||||||
<div class="w-full h-screen flex justify-center">
|
<div class="w-full h-screen flex justify-center">
|
||||||
<div
|
<div
|
||||||
class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col justify-between"
|
class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col justify-between">
|
||||||
>
|
@userDetailsSection(user)
|
||||||
@userDetailsSection("Hayden Hargreaves", "hhargreaves2006@gmail.com",
|
@logoutSection()
|
||||||
"https://lh3.googleusercontent.com/a/ACg8ocLeT6ltjQIkiBy1MgMJDbQxtBfMVfn8sP4e1t7d0bCJeHFdpcea=s96-c")
|
</div>
|
||||||
@logoutSection()
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,9 @@ import "github.com/a-h/templ"
|
|||||||
import templruntime "github.com/a-h/templ/runtime"
|
import templruntime "github.com/a-h/templ/runtime"
|
||||||
|
|
||||||
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
||||||
|
import "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||||
|
|
||||||
func userDetailsSection(name, email, url string) templ.Component {
|
func userDetailsSection(user domain.User) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
@ -36,9 +37,10 @@ func userDetailsSection(name, email, url string) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var2 string
|
var templ_7745c5c3_Var2 string
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(url)
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(
|
||||||
|
user.ImageUrl)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 8, Col: 111}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 10, Col: 19}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -49,9 +51,9 @@ func userDetailsSection(name, email, url string) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(user.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 10, Col: 56}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 12, Col: 63}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -62,9 +64,9 @@ func userDetailsSection(name, email, url string) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(email)
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 11, Col: 41}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 13, Col: 48}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -107,7 +109,7 @@ func logoutSection() templ.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProfilePage() templ.Component {
|
func ProfilePage(user domain.User) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||||
@ -136,8 +138,7 @@ func ProfilePage() templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = userDetailsSection("Hayden Hargreaves", "hhargreaves2006@gmail.com",
|
templ_7745c5c3_Err = userDetailsSection(user).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
"https://lh3.googleusercontent.com/a/ACg8ocLeT6ltjQIkiBy1MgMJDbQxtBfMVfn8sP4e1t7d0bCJeHFdpcea=s96-c").Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user