mirror of
https://github.com/Dvorinka/Trackeep.git
synced 2026-06-03 20:12:58 +00:00
144 lines
3.4 KiB
Go
144 lines
3.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/trackeep/backend/models"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// MemberHandler handles member-related requests
|
|
type MemberHandler struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewMemberHandler creates a new member handler
|
|
func NewMemberHandler(db *gorm.DB) *MemberHandler {
|
|
return &MemberHandler{db: db}
|
|
}
|
|
|
|
// GetMembers returns all members
|
|
func (h *MemberHandler) GetMembers(c *gin.Context) {
|
|
var users []models.User
|
|
|
|
// Get pagination parameters
|
|
page, _ := strconv.Atoi(c.Query("page"))
|
|
if page < 1 {
|
|
page = 1
|
|
}
|
|
limit, _ := strconv.Atoi(c.Query("limit"))
|
|
if limit < 1 {
|
|
limit = 50
|
|
}
|
|
offset := (page - 1) * limit
|
|
|
|
// Count total users
|
|
var total int64
|
|
h.db.Model(&models.User{}).Count(&total)
|
|
|
|
// Get users with pagination
|
|
if err := h.db.Offset(offset).Limit(limit).Order("created_at DESC").Find(&users).Error; err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch members"})
|
|
return
|
|
}
|
|
|
|
// Transform users to member response format
|
|
members := make([]map[string]interface{}, len(users))
|
|
for i, user := range users {
|
|
members[i] = map[string]interface{}{
|
|
"id": user.ID,
|
|
"name": user.FullName,
|
|
"email": user.Email,
|
|
"username": user.Username,
|
|
"role": "Member", // Default role, you might want to add role field to User model
|
|
"avatar": getInitials(user.FullName),
|
|
"joinedAt": formatTime(user.CreatedAt),
|
|
"theme": user.Theme,
|
|
"language": user.Language,
|
|
}
|
|
}
|
|
|
|
response := map[string]interface{}{
|
|
"members": members,
|
|
"total": total,
|
|
"page": page,
|
|
"limit": limit,
|
|
}
|
|
|
|
c.JSON(http.StatusOK, response)
|
|
}
|
|
|
|
// GetMemberStats returns member statistics
|
|
func (h *MemberHandler) GetMemberStats(c *gin.Context) {
|
|
var totalUsers int64
|
|
var activeUsers int64 // Users who joined in last 30 days
|
|
var newUsersThisMonth int64
|
|
|
|
// Total users
|
|
h.db.Model(&models.User{}).Count(&totalUsers)
|
|
|
|
// Active users (last 30 days)
|
|
thirtyDaysAgo := time.Now().AddDate(0, 0, -30)
|
|
h.db.Model(&models.User{}).Where("updated_at >= ?", thirtyDaysAgo).Count(&activeUsers)
|
|
|
|
// New users this month
|
|
now := time.Now()
|
|
startOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
|
h.db.Model(&models.User{}).Where("created_at >= ?", startOfMonth).Count(&newUsersThisMonth)
|
|
|
|
stats := map[string]interface{}{
|
|
"totalUsers": totalUsers,
|
|
"activeUsers": activeUsers,
|
|
"newUsersThisMonth": newUsersThisMonth,
|
|
}
|
|
|
|
c.JSON(http.StatusOK, stats)
|
|
}
|
|
|
|
// Helper functions
|
|
func getInitials(name string) string {
|
|
if name == "" {
|
|
return "U"
|
|
}
|
|
|
|
// Simple initials extraction - you might want to improve this
|
|
parts := strings.Fields(name)
|
|
if len(parts) >= 2 {
|
|
return strings.ToUpper(string(parts[0][0]) + string(parts[1][0]))
|
|
}
|
|
return strings.ToUpper(string(name[0]))
|
|
}
|
|
|
|
func formatTime(t time.Time) string {
|
|
duration := time.Since(t)
|
|
days := int(duration.Hours() / 24)
|
|
|
|
if days == 0 {
|
|
return "Today"
|
|
} else if days == 1 {
|
|
return "Yesterday"
|
|
} else if days < 7 {
|
|
return strconv.Itoa(days) + " days ago"
|
|
} else if days < 30 {
|
|
weeks := days / 7
|
|
return strconv.Itoa(weeks) + " week" + pluralS(weeks) + " ago"
|
|
} else if days < 365 {
|
|
months := days / 30
|
|
return strconv.Itoa(months) + " month" + pluralS(months) + " ago"
|
|
} else {
|
|
years := days / 365
|
|
return strconv.Itoa(years) + " year" + pluralS(years) + " ago"
|
|
}
|
|
}
|
|
|
|
func pluralS(n int) string {
|
|
if n == 1 {
|
|
return ""
|
|
}
|
|
return "s"
|
|
}
|