Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,42 @@ package api
import (
"path/filepath"
"runtime"

"github.com/gin-gonic/gin"
"gorm.io/gorm"

"userprofile-api/controllers"
)

// SetupRouter configures the API routes
func SetupRouter() *gin.Engine {
func SetupRouter(db *gorm.DB) *gin.Engine {
router := gin.Default()

// Get the absolute path to the templates directory
_, b, _, _ := runtime.Caller(0)
basePath := filepath.Dir(filepath.Dir(b))
templatesPath := filepath.Join(basePath, "templates/*")

// Setup template rendering
router.LoadHTMLGlob(templatesPath)


uc := controllers.NewUserController(db)

// Root handler shows a nice HTML table of all users
router.GET("/", controllers.HomePageHandler)
router.GET("/", uc.HomePageHandler)

// API version group
v1 := router.Group("/api/v1")
{
users := v1.Group("/users")
{
users.GET("", controllers.GetUsers)
users.GET("/:id", controllers.GetUser)
users.POST("", controllers.CreateUser)
users.PUT("/:id", controllers.UpdateUser)
users.GET("", uc.GetUsers)
users.GET("/:id", uc.GetUser)
users.POST("", uc.CreateUser)
users.PUT("/:id", uc.UpdateUser)
users.DELETE("/:id", uc.DeleteUser)
}
}

return router
}
143 changes: 100 additions & 43 deletions controllers/user_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,82 +3,139 @@ package controllers
import (
"log"
"net/http"
"strconv"

"github.com/gin-gonic/gin"
"gorm.io/gorm"

"userprofile-api/models"
)

// Sample user data
var users = []models.UserProfile{
{ID: "1", FullName: "John Doe", Emoji: "😀"},
{ID: "2", FullName: "Jane Smith", Emoji: "🚀"},
{ID: "3", FullName: "Robert Johnson", Emoji: "🎸"},
// UserController handles user-related HTTP requests.
type UserController struct {
DB *gorm.DB
}

// NewUserController creates a new UserController with the given database.
func NewUserController(db *gorm.DB) *UserController {
return &UserController{DB: db}
}

// HomePageHandler renders a HTML page displaying users in a table
func HomePageHandler(c *gin.Context) {
func (uc *UserController) HomePageHandler(c *gin.Context) {
log.Println("GET / endpoint called")

var users []models.UserProfile
if err := uc.DB.Order("id").Find(&users).Error; err != nil {
c.HTML(http.StatusInternalServerError, "users.html", gin.H{"Users": nil})
return
}

c.HTML(http.StatusOK, "users.html", gin.H{
"Users": users,
})
}

// GetUsers returns all users
func GetUsers(c *gin.Context) {
func (uc *UserController) GetUsers(c *gin.Context) {
log.Println("GET /api/v1/users endpoint called")

var users []models.UserProfile
if err := uc.DB.Order("id").Find(&users).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch users"})
return
}

c.JSON(http.StatusOK, users)
}

// GetUser returns a single user by ID
func GetUser(c *gin.Context) {
id := c.Param("id")

for _, user := range users {
if user.ID == id {
c.JSON(http.StatusOK, user)
return
}
func (uc *UserController) GetUser(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}

c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})

var user models.UserProfile
if err := uc.DB.First(&user, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}

c.JSON(http.StatusOK, user)
}

// CreateUser adds a new user
func CreateUser(c *gin.Context) {
var newUser models.UserProfile

if err := c.ShouldBindJSON(&newUser); err != nil {
func (uc *UserController) CreateUser(c *gin.Context) {
var req models.CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

// For simplicity, we're just appending to the slice
// In a real application, you would use a database
users = append(users, newUser)

c.JSON(http.StatusCreated, newUser)

user := models.UserProfile{
FullName: req.FullName,
Emoji: req.Emoji,
}

if err := uc.DB.Create(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
return
}

c.JSON(http.StatusCreated, user)
}

// UpdateUser updates an existing user
func UpdateUser(c *gin.Context) {
id := c.Param("id")
var updatedUser models.UserProfile

if err := c.ShouldBindJSON(&updatedUser); err != nil {
func (uc *UserController) UpdateUser(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}

var user models.UserProfile
if err := uc.DB.First(&user, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}

var req models.UpdateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

for i, user := range users {
if user.ID == id {
updatedUser.ID = id // Ensure ID doesn't change
users[i] = updatedUser
c.JSON(http.StatusOK, updatedUser)
return
}

user.FullName = req.FullName
user.Emoji = req.Emoji

if err := uc.DB.Save(&user).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user"})
return
}
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})

c.JSON(http.StatusOK, user)
}

// DeleteUser removes a user by ID TODO
// DeleteUser removes a user by ID
func (uc *UserController) DeleteUser(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}

result := uc.DB.Delete(&models.UserProfile{}, id)
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete user"})
return
}

if result.RowsAffected == 0 {
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}

c.JSON(http.StatusOK, gin.H{"message": "User deleted"})
}
Loading